{"record":{"id":"1c22b18ce9ba745a","repo":"jdx/mise","slug":"remote-action-result-is-missing-its-output-root","errorCode":null,"errorMessage":"remote action result is missing its output root","messagePattern":"remote action result is missing its output root","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/task/task_cache_store.rs","lineNumber":418,"sourceCode":"        let metadata_bytes = self\n            .client\n            .get_blob(metadata, CLIENT_METADATA_MEDIA_TYPE)\n            .await?;\n        let metadata: RemoteClientMetadata = serde_json::from_slice(&metadata_bytes)?;\n        if canonical_json(&serde_json::to_value(&metadata)?)? != metadata_bytes {\n            bail!(\"remote cache client metadata is not canonical JSON\");\n        }\n        let mut manifest = metadata.into_manifest(key)?;\n        for root in &manifest.roots {\n            validate_cache_path(root)?;\n        }\n        let artifact = match &result.output_root {\n            Some(root) => {\n                let temporary = materialize_remote_tree(self, root).await?;\n                Some(TaskCacheStoreArtifact::temporary(temporary))\n            }\n            None if manifest.roots.is_empty() => None,\n            None => bail!(\"remote action result is missing its output root\"),\n        };\n        manifest.artifact_checksum = Some(calculate_artifact_checksum(\n            &manifest,\n            artifact.as_ref().map(TaskCacheStoreArtifact::path),\n        )?);\n        let manifest = serde_json::to_vec(&manifest)?;\n        Ok(Some(TaskCacheStoreEntry { manifest, artifact }))\n    }\n\n    fn begin_write(&self, key: &str) -> Result<TaskCacheStoreWrite> {\n        validate_remote_key(key)?;\n        file::create_dir_all(&self.staging_dir)?;\n        let nonce = crate::rand::random_string(8);\n        Ok(TaskCacheStoreWrite {\n            artifact_path: self.staging_dir.join(format!(\"{key}.part-{nonce}.tar.zst\")),\n            manifest_path: self.staging_dir.join(format!(\"{key}.part-{nonce}.json\")),\n        })\n    }","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/task/task_cache_store.rs#L400-L436","documentation":"A downloaded remote action result must include an output-root tree when its manifest lists roots (files to restore). If output_root is absent while roots is non-empty, the entry is internally inconsistent — metadata promises artifacts that were never uploaded — and mise refuses to fabricate them.","triggerScenarios":"get() matches result.output_root = None with a manifest whose roots are non-empty — typically a commit interrupted after metadata upload but before the artifact tree, leaving a half-written entry.","commonSituations":"Upload killed mid-transaction (network drop, CI cancel, timeout); a writer bug in an experimental build; lifecycle rules deleting blobs but not metadata.","solutions":["Purge the offending remote key (or its prefix) so the task re-runs and writes a complete entry","If it recurs, look for interrupted uploads: CI timeouts, proxy body-size limits, flaky networks","Report upstream if entries are consistently half-written on a current pinned mise"],"exampleFix":"# before: half-uploaded entry keeps failing restore\n# after: evict and re-run\naws s3 rm --recursive s3://cache/tasks/<key-prefix>\nmise run build","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// a half-written remote entry is a miss; evict and rebuild\nmatch fetch_remote_entry(&key).await {\n    Ok(e) => Some(e),\n    Err(err) if err.to_string().contains(\"remote action result is missing its output root\") => {\n        evict_remote(&key).await;\n        None\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Let CI cancel gracefully instead of killing uploads mid-flight","Alert on repeated half-written entries — it signals upload flakiness","Check lifecycle rules are not deleting artifact blobs independently of metadata"],"tags":["mise","task-cache","remote-cache","integrity"],"backgroundTag":"cache-metadata-invalid","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}