jdx/mise · error · eyre::Report
cached rustc output set does not match the invocation
Error message
cached rustc output set does not match the invocation
What it means
validated_outputs() requires the cached directory.files count to equal the number of outputs the current invocation expects (emitted files plus the dep-info file) (src/cache/rustc.rs:557-559). A count mismatch means the cached entry does not describe this invocation's output set — the action digest and the stored directory disagree, which in practice means cross-version cache pollution or a tampered/poisoned entry; the restore is refused rather than partially applied.
Source
Thrown at src/cache/rustc.rs:558
bail!("cached rustc output directory has unsupported entries");
}
let mut expected = outputs
.files
.iter()
.chain(std::iter::once(&outputs.dep_info))
.map(|path| {
let name = path
.file_name()
.and_then(|name| name.to_str())
.ok_or_else(|| eyre::eyre!("expected rustc output name is not UTF-8"))?;
if path.parent() != Some(outputs.directory.as_path()) {
bail!("expected rustc output escapes its output directory");
}
Ok((name.to_string(), path.clone()))
})
.collect::<Result<BTreeMap<_, _>>>()?;
if directory.files.len() != expected.len() {
bail!("cached rustc output set does not match the invocation");
}
let mut files = Vec::with_capacity(directory.files.len());
for node in directory.files {
validate_file_mode(&node)?;
let destination = expected
.remove(&node.name)
.ok_or_else(|| eyre::eyre!("cached rustc output is unexpected: {}", node.name))?;
files.push((node, destination));
}
if !expected.is_empty() {
bail!("cached rustc output set is incomplete");
}
Ok(files)
}
fn compiler_identity(rustc: &OsStr) -> Result<CompilerIdentity> {
let executable = resolve_executable(rustc)?;
let environment = ["RUSTUP_HOME", "RUSTUP_TOOLCHAIN"]View on GitHub (pinned to 6f52dcdf99)
Solutions
- Purge the affected cache/namespace and rebuild from a single trusted mise version
- Keep one mise version per namespace and keep namespaces private per project/team
- If it persists on a private cache with matched versions, investigate integrity — this guard exists to block poisoned entries from being restored
Defensive patterns
Strategy: fallback
Validate before calling
fn output_count_matches(directory: &CacheDirectory, outputs: &RustcOutputs) -> bool {
directory.files.len() == outputs.files.len() + 1 // + dep-info
} Try / catch
Refuse partial restores: on any set mismatch, discard the cached entry entirely and recompile — never merge cached files with locally produced ones.
Prevention
- One mise version per remote namespace
- Keep namespaces private per project/team
- Investigate persistent mismatches as potential cache poisoning, not flakiness
When it happens
Trigger: A stored CacheDirectory with extra or missing file nodes relative to the invocation's expected outputs: a remote cache shared across mise versions whose output-set parsing differs (e.g. dep-info handling changed), or a deliberately crafted entry aimed at the CAS.
Common situations: Mixed mise versions writing one remote namespace; shared CI caches across teams on different versions; a compromised or untrusted remote cache.
Related errors
- cached rustc output set is incomplete
- cached {description} failed digest verification
- rustc produced no cacheable outputs
- rustc output is not a regular file: {}
- cached rustc output has an unsafe file mode: {}
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/1222c3118615f244.
Report an issue: GitHub.