{"record":{"id":"8b30d3aa5456d108","repo":"jdx/mise","slug":"rustc-output-is-not-a-regular-file","errorCode":null,"errorMessage":"rustc output is not a regular file: {}","messagePattern":"rustc output is not a regular file: (.+?)","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"warning","filePath":"src/cache/rustc.rs","lineNumber":765,"sourceCode":"    action_bytes: &[u8],\n    outputs: &[PathBuf],\n    output: &Output,\n) -> Result<()> {\n    if outputs.is_empty() {\n        bail!(\"rustc produced no cacheable outputs\");\n    }\n    let staging = staging_directory()?;\n    let mut blobs = vec![staged_bytes(staging.path(), \"action.json\", action_bytes)?];\n    let stdout = staged_bytes(staging.path(), \"stdout\", &output.stdout)?;\n    let stderr = staged_bytes(staging.path(), \"stderr\", &output.stderr)?;\n    blobs.extend([stdout.clone(), stderr.clone()]);\n\n    let mut files = Vec::with_capacity(outputs.len());\n    for path in outputs {\n        let metadata = std::fs::metadata(path)\n            .wrap_err_with(|| format!(\"failed to inspect rustc output {}\", path.display()))?;\n        if !metadata.is_file() {\n            bail!(\"rustc output is not a regular file: {}\", path.display());\n        }\n        let digest = CacheDigest::blake3_file(path)?;\n        blobs.push((digest.clone(), path.clone()));\n        files.push(CacheFileNode {\n            digest,\n            executable: false,\n            mode: file_mode(&metadata),\n            name: path\n                .file_name()\n                .and_then(|name| name.to_str())\n                .ok_or_else(|| eyre::eyre!(\"rustc output name is not UTF-8\"))?\n                .to_string(),\n        });\n    }\n    files.sort_by(|left, right| left.name.cmp(&right.name));\n\n    let metadata = canonical_json(&RustcMetadata {\n        version: 1,","sourceCodeStart":747,"sourceCodeEnd":783,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/cache/rustc.rs#L747-L783","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","solutions":["Re-run the task: outputs are recreated and publication succeeds on the next pass","Ensure nothing mutates target/ outputs while the cached task runs (move post-processing to a separate task)","Avoid symlink tricks inside the target directory for cached tasks"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"fn all_regular_files(paths: &[PathBuf]) -> bool {\n    paths\n        .iter()\n        .all(|p| std::fs::metadata(p).is_ok_and(std::fs::Metadata::is_file))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep post-build file moves/deletes out of cached tasks","Avoid symlinks inside the cargo target directory","Clean target/ leftovers after crashed builds before enabling the cache"],"tags":["rust","cache","outputs","filesystem","publish"],"backgroundTag":"artifact-not-regular-file","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}