{"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":2179,"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":2161,"sourceCodeEnd":2197,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/remote.rs#L2161-L2197","documentation":"`validate_value` is the base check for every remote field (kind describes which): the value must be non-empty and must not contain a NUL byte, since NUL cannot appear in command-line arguments and empty values indicate missing configuration. It underpins the stricter `validate_ssh_atom` checks.","triggerScenarios":"An unset or blank remote host/user/path is passed to the remote transport, or a value containing a literal NUL (e.g. from corrupted env vars or binary-contaminated config) reaches the validator.","commonSituations":"Environment variable like MISE_REMOTE_HOST left empty; templated config where a variable expanded to nothing; programmatic callers constructing args from C-string sources that got truncated at a NUL.","solutions":["Set the missing remote field (host/user/path) to a concrete non-empty value in config or environment","Check where the value comes from (env var, mise.toml) for truncation or garbage bytes and fix the source","Re-export/re-set the variable without embedded NULs, then rerun"],"exampleFix":"// before\n# mise.toml or env\nMISE_REMOTE_HOST=\"\"    # empty -> bail\n// after\nMISE_REMOTE_HOST=\"deploy@build.example.com\"","handlingStrategy":"validation","validationCode":"fn is_valid_remote_value(v: &str) -> bool {\n    !v.is_empty() && !v.contains('\\\\0')\n}\n// before calling:\nif !is_valid_remote_value(&host) { eprintln!(\"remote host unset or invalid\"); std::process::exit(1); }","typeGuard":null,"tryCatchPattern":"if let Err(e) = op() {\n    if e.to_string().contains(\"cannot be empty or contain NUL\") {\n        eprintln!(\"set the remote host/user config and retry: {e}\");\n    }\n    return Err(e.into());\n}","preventionTips":["Fail fast on empty env/config values before launching remote ops","Beware C-string truncation when building values programmatically","Lint mise.toml/env files for blank required remote fields"],"tags":["remote","ssh","validation","empty-value"],"backgroundTag":"empty-required-field","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}