jdx/mise · error · eyre::Report

cached rustc output directory has unsupported entries

Error message

cached rustc output directory has unsupported entries

What it means

validated_outputs() only accepts flat, version-1 output directories: directory.version must equal 1 and the directories/symlinks lists must be empty (src/cache/rustc.rs:538-541). The rustc adapter caches plain files only, so an entry using a newer format version or containing nested directories/symlinks cannot be safely restored and is rejected. This guard exists to stop a future-format entry from being interpreted with today's semantics.

Source

Thrown at src/cache/rustc.rs:540

    Ok(value)
}

fn read_verified_blob(path: &Path, digest: &CacheDigest, description: &str) -> Result<Vec<u8>> {
    let mut bytes = Vec::new();
    std::fs::File::open(path)?.read_to_end(&mut bytes)?;
    if !digest.matches_bytes(&bytes)? {
        bail!("cached {description} failed digest verification");
    }
    Ok(bytes)
}

fn validated_outputs(
    directory: CacheDirectory,
    outputs: &RustcOutputs,
) -> Result<Vec<(CacheFileNode, PathBuf)>> {
    if directory.version != 1 || !directory.directories.is_empty() || !directory.symlinks.is_empty()
    {
        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");

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Upgrade mise to at least the version that wrote the cache entries
  2. Or purge the cache/namespace so unreadable entries disappear and repopulate with the current version
  3. Use per-mise-version remote namespaces so format changes never mix (namespace = 'ci-2026-1')

Example fix

# before: one namespace shared across mise versions
[settings]
task.cache.remote_namespace = 'ci'
# after: namespace pinned to the writer's mise version
[settings]
task.cache.remote_namespace = 'ci-2026-1'
Defensive patterns

Strategy: fallback

Validate before calling

fn supported_cache_directory(d: &CacheDirectory) -> bool {
    d.version == 1 && d.directories.is_empty() && d.symlinks.is_empty()
}

Prevention

When it happens

Trigger: Restoring an action whose CacheDirectory was written by a newer mise that bumped the version field or started storing directories/symlinks; a remote namespace shared across mise versions where a newer client populated entries your version cannot read.

Common situations: Downgrading mise after a newer version already populated the cache; CI caches written by a refreshed image while an older local mise reads them; mixed-version contributor bases on one shared remote cache.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/dd416b28198541f3. Report an issue: GitHub.