{"record":{"id":"144fb2e726cdfa0a","repo":"hashicorp/packer","slug":"write-attestation-q-w","errorCode":null,"errorMessage":"write attestation %q: %w","messagePattern":"write attestation %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"post-processor/provenance/post-processor.go","lineNumber":289,"sourceCode":"\n\tstatement := internalprovenance.WrapInToto(subjects, predicateType, predicate)\n\tif err := p.writeAttestation(ctx, ui, statement, paths.SBOMAttestation); err != nil {\n\t\treturn err\n\t}\n\n\tui.Say(fmt.Sprintf(\"Wrote SBOM to %s\", paths.SBOMRaw))\n\treturn nil\n}\n\nfunc (p *PostProcessor) writeAttestation(ctx context.Context, ui packersdk.Ui, statement interface{}, outputPath string) error {\n\tif p.config.SigningMode == internalattestation.SigningModeNone {\n\t\tpayload, err := json.MarshalIndent(statement, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"marshal attestation payload: %w\", err)\n\t\t}\n\n\t\tif err := atomicWriteFile(outputPath, payload, 0664); err != nil {\n\t\t\treturn fmt.Errorf(\"write attestation %q: %w\", outputPath, err)\n\t\t}\n\n\t\tui.Say(fmt.Sprintf(\"Wrote attestation to %s\", outputPath))\n\t\treturn nil\n\t}\n\n\tbackendConfig, err := p.signingBackendConfig()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tsigner, verifier, err := p.signingResources(ctx, backendConfig)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tpayload, err := internalattestation.MarshalPayload(statement)\n\tif err != nil {","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/post-processor/provenance/post-processor.go#L271-L307","documentation":"After marshaling the unsigned attestation, writeAttestation writes it to `outputPath` via atomicWriteFile. Any filesystem error (permissions, missing directory, disk full, path is a directory) is wrapped as `write attestation %q: %w` with the path quoted.","triggerScenarios":"PostProcess/writeSBOMAttestation with an output_path whose parent directory doesn't exist, is read-only, or is owned by another user; or outputPath itself is an existing directory.","commonSituations":"Running packer in a container where the output dir was never created; SELinux/read-only mounts; specifying a path inside a non-existent `output_dir`.","solutions":["Create the parent directory: `mkdir -p $(dirname <output_path>)`.","Check write permissions on the target directory (`ls -ld`, run as the right user).","Ensure outputPath is a file path, not an existing directory.","Check disk space and mount status if the error mentions 'no space left' or 'read-only'."],"exampleFix":"// before\npost-processor \"provenance\" { output_path = \"/att/manifest.json\" } // /att missing\n// after\npost-processor \"provenance\" { output_path = \"./attestations/manifest.json\" } // dir pre-created","handlingStrategy":"validation","validationCode":"// check the output path is writable before the build\npath := cfg.OutputPath\nif dir := filepath.Dir(path); dir != \".\" {\n    if err := os.MkdirAll(dir, 0o755); err != nil { return err }\n}\nif info, err := os.Stat(path); err == nil && info.IsDir() {\n    return fmt.Errorf(\"output_path %q is a directory\", path)\n}\nif f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o664); err != nil {\n    return err\n} else { f.Close() }","typeGuard":null,"tryCatchPattern":"if err := pp.PostProcess(ctx, ui, artifact); err != nil {\n    if strings.Contains(err.Error(), \"write attestation\") {\n        // check permissions/existence of the quoted path, then retry once after mkdir\n    }\n}","preventionTips":["Pre-create output directories in CI before running packer.","Run packer as a user with write access to output_dir.","Avoid paths on read-only or tmpfs mounts for artifacts.","Verify disk space before long builds."],"tags":["filesystem","permissions","attestation","provenance"],"backgroundTag":"file-write-failed","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}