jdx/mise · warning · eyre::Report

rustc output is not a regular file: {}

Error message

rustc output is not a regular file: {}

What it means

When publishing, each output path must exist and be a regular file — std::fs::metadata follows symlinks, and is_file() is false for directories, FIFOs, sockets, and broken symlinks (src/cache/rustc.rs:761-766). Non-regular outputs cannot be safely content-addressed and atomically restored, so publication aborts (warning only; the build result is untouched).

Source

Thrown at src/cache/rustc.rs:765

    action_bytes: &[u8],
    outputs: &[PathBuf],
    output: &Output,
) -> Result<()> {
    if outputs.is_empty() {
        bail!("rustc produced no cacheable outputs");
    }
    let staging = staging_directory()?;
    let mut blobs = vec![staged_bytes(staging.path(), "action.json", action_bytes)?];
    let stdout = staged_bytes(staging.path(), "stdout", &output.stdout)?;
    let stderr = staged_bytes(staging.path(), "stderr", &output.stderr)?;
    blobs.extend([stdout.clone(), stderr.clone()]);

    let mut files = Vec::with_capacity(outputs.len());
    for path in outputs {
        let metadata = std::fs::metadata(path)
            .wrap_err_with(|| format!("failed to inspect rustc output {}", path.display()))?;
        if !metadata.is_file() {
            bail!("rustc output is not a regular file: {}", path.display());
        }
        let digest = CacheDigest::blake3_file(path)?;
        blobs.push((digest.clone(), path.clone()));
        files.push(CacheFileNode {
            digest,
            executable: false,
            mode: file_mode(&metadata),
            name: path
                .file_name()
                .and_then(|name| name.to_str())
                .ok_or_else(|| eyre::eyre!("rustc output name is not UTF-8"))?
                .to_string(),
        });
    }
    files.sort_by(|left, right| left.name.cmp(&right.name));

    let metadata = canonical_json(&RustcMetadata {
        version: 1,

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Re-run the task: outputs are recreated and publication succeeds on the next pass
  2. Ensure nothing mutates target/ outputs while the cached task runs (move post-processing to a separate task)
  3. Avoid symlink tricks inside the target directory for cached tasks
Defensive patterns

Strategy: fallback

Validate before calling

fn all_regular_files(paths: &[PathBuf]) -> bool {
    paths
        .iter()
        .all(|p| std::fs::metadata(p).is_ok_and(std::fs::Metadata::is_file))
}

Prevention

When it happens

Trigger: An output path disappearing or being replaced between compilation finishing and publish_result inspecting it: a build script moved/deleted the file, a symlinked output whose target is gone, or a directory sitting where a file was expected (e.g. a dep-info path colliding with a directory).

Common situations: Concurrent cargo invocations or post-build scripts reshaping target/; symlinked CARGO_TARGET_DIR entries; leftovers from a crashed earlier build; aggressive cleanup tools running during the build.

Related errors


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