jdx/mise · error

remote {kind} cannot be empty or contain NUL

Error message

remote {kind} cannot be empty or contain NUL

What it means

validate_value is the base check applied to remote configuration scalars (host, user, SSH options, archive excludes, remote mise command): the value must be non-empty and contain no NUL byte. This error means a configured remote value is the empty string or has an embedded \0 — either impossible to pass to the OS or a sign of corrupted config.

Source

Thrown at src/system/remote.rs:1467

fn absolutize(path: &Path) -> Result<PathBuf> {
    if path.is_absolute() {
        Ok(path.to_path_buf())
    } else {
        Ok(std::env::current_dir()?.join(path))
    }
}

fn validate_ssh_atom(kind: &str, value: &str) -> Result<()> {
    validate_value(kind, value)?;
    if value.starts_with('-') || value.chars().any(char::is_whitespace) {
        bail!("invalid remote {kind}: {value}");
    }
    Ok(())
}

fn validate_value(kind: &str, value: &str) -> Result<()> {
    if value.is_empty() || value.contains('\0') {
        bail!("remote {kind} cannot be empty or contain NUL");
    }
    Ok(())
}

fn validate_staging_path(path: &str) -> Result<()> {
    if !path.starts_with("/tmp/mise-bootstrap.")
        || path["/tmp/mise-bootstrap.".len()..].is_empty()
        || path.chars().any(char::is_whitespace)
    {
        bail!("remote mktemp returned an unsafe staging path: {path:?}");
    }
    Ok(())
}

fn validated_remote_command(command: &str) -> Result<String> {
    if !command.starts_with('/') || command.contains(['\0', '\n', '\r']) {
        bail!("bootstrap_command returned an unsafe mise path: {command:?}");
    }

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Find the empty/NUL value in the remote host config (mise.toml [remote.hosts.*], environment overrides like MISE_REMOTE_*)
  2. Remove the key entirely instead of setting it to "" when you want to clear it
  3. If merging layers, check mise config ls / the effective config for which layer supplies the value
  4. Sanitize programmatic config generation to skip empty values

Example fix

# before (mise.toml)
[remote.hosts.build]
ssh = "ci@build"
user = ""

# after
[remote.hosts.build]
ssh = "ci@build"
Defensive patterns

Strategy: validation

Validate before calling

# reject empty remote values when generating config
: "${MISE_REMOTE_HOST:?must be set and non-empty}"

Type guard

fn valueValid(value: &str) -> bool {
    !value.is_empty() && !value.contains('\0')
}

Try / catch

for option in &host.ssh_options {
    if !valueValid(option) {
        return Err(eyre::eyre!("empty/NUL SSH option in config layer"));
    }
}
host.validate()?;

Prevention

When it happens

Trigger: RemoteHost::validate walking ssh_options/exclude entries, remote_mise, or other scalars where the TOML value is "" (e.g. user = "" set to 'unset' a parent value) or a string smuggled a NUL (only possible via programmatic construction, since TOML cannot encode NUL directly).

Common situations: Users blanking inherited keys with empty strings when merging configs; automation templates emitting empty placeholders; values sourced from environment variables that are unset and interpolated as ''. NUL in practice appears only from bugs in tooling that builds the config.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/fab2d130d2fb4c87. Report an issue: GitHub.