{"record":{"id":"fab2d130d2fb4c87","repo":"jdx/mise","slug":"remote-kind-cannot-be-empty-or-contain-nul","errorCode":null,"errorMessage":"remote {kind} cannot be empty or contain NUL","messagePattern":"remote (.+?) cannot be empty or contain NUL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/remote.rs","lineNumber":1467,"sourceCode":"fn absolutize(path: &Path) -> Result<PathBuf> {\n    if path.is_absolute() {\n        Ok(path.to_path_buf())\n    } else {\n        Ok(std::env::current_dir()?.join(path))\n    }\n}\n\nfn validate_ssh_atom(kind: &str, value: &str) -> Result<()> {\n    validate_value(kind, value)?;\n    if value.starts_with('-') || value.chars().any(char::is_whitespace) {\n        bail!(\"invalid remote {kind}: {value}\");\n    }\n    Ok(())\n}\n\nfn validate_value(kind: &str, value: &str) -> Result<()> {\n    if value.is_empty() || value.contains('\\0') {\n        bail!(\"remote {kind} cannot be empty or contain NUL\");\n    }\n    Ok(())\n}\n\nfn validate_staging_path(path: &str) -> Result<()> {\n    if !path.starts_with(\"/tmp/mise-bootstrap.\")\n        || path[\"/tmp/mise-bootstrap.\".len()..].is_empty()\n        || path.chars().any(char::is_whitespace)\n    {\n        bail!(\"remote mktemp returned an unsafe staging path: {path:?}\");\n    }\n    Ok(())\n}\n\nfn validated_remote_command(command: &str) -> Result<String> {\n    if !command.starts_with('/') || command.contains(['\\0', '\\n', '\\r']) {\n        bail!(\"bootstrap_command returned an unsafe mise path: {command:?}\");\n    }","sourceCodeStart":1449,"sourceCodeEnd":1485,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/remote.rs#L1449-L1485","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Find the empty/NUL value in the remote host config (mise.toml [remote.hosts.*], environment overrides like MISE_REMOTE_*)","Remove the key entirely instead of setting it to \"\" when you want to clear it","If merging layers, check mise config ls / the effective config for which layer supplies the value","Sanitize programmatic config generation to skip empty values"],"exampleFix":"# before (mise.toml)\n[remote.hosts.build]\nssh = \"ci@build\"\nuser = \"\"\n\n# after\n[remote.hosts.build]\nssh = \"ci@build\"","handlingStrategy":"validation","validationCode":"# reject empty remote values when generating config\n: \"${MISE_REMOTE_HOST:?must be set and non-empty}\"","typeGuard":"fn valueValid(value: &str) -> bool {\n    !value.is_empty() && !value.contains('\\0')\n}","tryCatchPattern":"for option in &host.ssh_options {\n    if !valueValid(option) {\n        return Err(eyre::eyre!(\"empty/NUL SSH option in config layer\"));\n    }\n}\nhost.validate()?;","preventionTips":["Delete config keys rather than blanking them when overriding layers","Fail fast in templates when a remote variable is unset","Review 'mise config ls' output for empty strings in remote entries"],"tags":["remote","ssh","validation","config","empty-value"],"backgroundTag":"ssh-argument-validation-failed","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}