jdx/mise · error
invalid completion specification path
Error message
invalid completion specification path
What it means
decode_spec_path decodes a base64url-encoded path embedded in a generated completion loader back into a PathBuf. On Windows the encoding is UTF-16LE (each character = 2 bytes); if the decoded byte vector has an odd length, it cannot be a valid UTF-16 sequence, so decoding would corrupt the path and mise bails instead. This guards against a truncated or hand-mangled encoded string.
Source
Thrown at src/packslip/completions.rs:43
.flat_map(u16::to_le_bytes)
.collect()
};
base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(bytes)
}
pub(crate) fn decode_spec_path(encoded: &str) -> eyre::Result<std::path::PathBuf> {
use base64::Engine;
let bytes = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(encoded)?;
#[cfg(unix)]
let path = {
use std::os::unix::ffi::OsStringExt;
std::ffi::OsString::from_vec(bytes)
};
#[cfg(windows)]
let path = {
use std::os::windows::ffi::OsStringExt;
if !bytes.len().is_multiple_of(2) {
eyre::bail!("invalid completion specification path");
}
let wide: Vec<_> = bytes
.chunks_exact(2)
.map(|b| u16::from_le_bytes([b[0], b[1]]))
.collect();
std::ffi::OsString::from_wide(&wide)
};
Ok(path.into())
}
pub(crate) fn clear(shell: &str) -> &'static str {
match shell {
"bash" | "zsh" => {
"if typeset -f __mise_clear_completions >/dev/null; then __mise_clear_completions; unset -f __mise_clear_completions; fi\n"
}
"fish" => {
"if functions -q __mise_clear_completions; __mise_clear_completions; functions -e __mise_clear_completions; end\n"
}View on GitHub (pinned to afd2eddd3a)
Solutions
- Regenerate the completion loader: rerun activation (`mise activate <shell>`) or `mise completion <shell> --tool <tool>` so the encoded path is rebuilt.
- Do not hand-edit the base64 constant inside the loader script; replace the whole script instead.
- Verify the loader file was not truncated by your editor or shell config tooling (check for intact quotes and length).
Example fix
// before: hand-edited loader constant __usage_complete_path aGVsbG8gd29ybA // after: regenerate mise activate pwsh # rewrites the loader with a fresh, intact encoded path
Defensive patterns
Strategy: try-catch
Validate before calling
fn valid_b64url_len(s: &str) -> bool {
base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(s)
.map(|b| b.len() % 2 == 0)
.unwrap_or(false) // on Windows targets
} Type guard
fn decodable_spec_path(encoded: &str) -> bool { decode_spec_path(encoded).is_ok() } Try / catch
match decode_spec_path(&encoded) {
Ok(path) => load_spec(&path),
Err(e) => {
eprintln!("loader constant corrupt ({e}); regenerating");
regenerate_loader(shell, tool)?;
}
} Prevention
- Never hand-edit the base64 constant inside generated loader scripts.
- Regenerate loaders after upgrading mise or copying configs between machines.
- Watch for editor/shell-config tooling that reflows or truncates long single-line scripts.
When it happens
Trigger: A completion loader script (generated by derive_from_spec embedding the base64url spec path) whose encoded path constant was truncated, edited, or produced by an encoder that dropped a byte — decode yields an odd-length byte vector on Windows.
Common situations: Shell config mangling the generated script (line wrapping, editors stripping characters); copying a loader between machines with a corrupted constant; an old loader after a mise change in encoding.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- TEMP is too long to replace mise.exe safely ({len} UTF-16 co
- Ruby engine '{}' is not supported on Windows. Only standard
- only available on unix
- brew-cask: completion executable '{}' is ambiguous: {}
- brew-cask: failed to generate {} completions from {}: {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/a720b68adf6382c3.
Report an issue: GitHub.