{"record":{"id":"ae994403e396cef8","repo":"jdx/mise","slug":"remote-mise-candidate-discovery-returned-a-truncat","errorCode":null,"errorMessage":"remote mise candidate discovery returned a truncated response","messagePattern":"remote mise candidate discovery returned a truncated response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/remote.rs","lineNumber":637,"sourceCode":"  case \"$1\" in\n    /*) if [ -x \"$1\" ]; then printf '%s\\000' \"$1\"; fi ;;\n  esac\n}\nold_ifs=$IFS\nIFS=:\nfor directory in $PATH; do\n  if [ -z \"$directory\" ]; then directory=.; fi\n  emit_mise_candidate \"$directory/mise\"\ndone\nIFS=$old_ifs\nfor candidate in \"$HOME/.local/bin/mise\" \"$HOME/.local/share/mise/bin/mise\" \"$HOME/.cargo/bin/mise\" /usr/local/bin/mise /opt/homebrew/bin/mise; do\n  emit_mise_candidate \"$candidate\"\ndone\"#\n}\n\nfn parse_remote_mise_candidates(output: &str) -> Result<Vec<String>> {\n    if !output.is_empty() && !output.ends_with('\\0') {\n        bail!(\"remote mise candidate discovery returned a truncated response\");\n    }\n    output\n        .split_terminator('\\0')\n        .map(validated_remote_command)\n        .collect::<Result<IndexSet<_>>>()\n        .map(IndexSet::into_iter)\n        .map(Iterator::collect)\n}\n\n#[derive(Clone, Debug, Eq, PartialEq)]\nstruct RemoteMiseIdentity {\n    version: String,\n    fingerprint: String,\n}\n\nfn remote_mise_candidate_identities(\n    session: &SshSession<'_>,\n    candidates: &[String],","sourceCodeStart":619,"sourceCodeEnd":655,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/remote.rs#L619-L655","documentation":"mise discovers remote mise executables by running a POSIX script under sh -lc that prints each absolute executable path terminated with a NUL byte; parse_remote_mise_candidates() treats a non-empty response that does not end in NUL as truncated. Any output appended after the candidate list — a chatty login profile, a motd banner, or a shell whose printf cannot emit \\0 — breaks the NUL-termination invariant and aborts.","triggerScenarios":"discover_remote_mise_candidates() or the post-bootstrap_command candidate scan running `sh -lc <script>` where the remote login shell sources .profile/.bashrc/.zprofile that echoes text to stdout; a remote /bin/sh with a non-POSIX printf that mangles or drops the '\\000' escape; ssh output truncation cutting the final NUL.","commonSituations":"Cloud images and hardened servers that print banners or last-login messages for login shells; nvm/conda/module init snippets echoing status; admins who add echo lines to /etc/profile; exotic or ancient remote shells.","solutions":["Silence stdout noise from the remote login environment: guard echo/banner lines in ~/.profile, ~/.bashrc, /etc/profile with [ -z \"$PS1\" ] && return or send them to stderr","Verify the round trip manually: ssh <host> sh -lc 'printf x\\\\000' | od -c should show a 0000-escaped byte","Bypass discovery entirely by setting remote_mise (known remote path) or mise_bin (upload a local binary) for that host"],"exampleFix":"# before (~/.profile on the remote host)\necho \"Welcome to build-server!\"\nexport NVM_DIR=\"$HOME/.nvm\"\n\n# after — non-interactive shells stay silent on stdout\nif [ -n \"$PS1\" ]; then echo \"Welcome to build-server!\"; fi\nexport NVM_DIR=\"$HOME/.nvm\"","handlingStrategy":"fallback","validationCode":"# preflight: the remote login shell must round-trip NUL-terminated stdout\nssh <host> sh -lc 'printf x\\\\000' | od -An -c | grep -q '\\\\0' && echo ok || echo 'login shell pollutes stdout or drops NUL'","typeGuard":null,"tryCatchPattern":"if e.to_string().contains(\"truncated response\") {\n    // quiet remote login-shell stdout noise, or set remote_mise/mise_bin to skip discovery\n}","preventionTips":["Keep remote .profile/.bashrc silent on stdout for non-interactive shells (guard with [ -n \"$PS1\" ])","Send banners and motd text to stderr, never stdout","Pin remote_mise or mise_bin on hosts known to have chatty login environments"],"tags":["mise","bootstrap","remote","ssh","shell","output-pollution"],"backgroundTag":"remote-shell-output-pollution","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}