{"record":{"id":"f353cc00f6e22315","repo":"wagoodman/dive","slug":"cannot-open-export-file-w","errorCode":null,"errorMessage":"cannot open export file: %w","messagePattern":"cannot open export file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/dive/cli/internal/command/adapter/exporter.go","lineNumber":54,"sourceCode":"\t\t\tOnSuccess:    \"Exported details\",\n\t\t},\n\t\tHideOnSuccess:      false,\n\t\tHideStageOnSuccess: false,\n\t\tID:                 analysis.Image,\n\t\tContext:            fmt.Sprintf(\"[file: %s]\", path),\n\t})\n\n\tbytes, err := export.NewExport(analysis).Marshal()\n\tif err != nil {\n\t\tmon.SetError(err)\n\t\treturn fmt.Errorf(\"cannot marshal export payload: %w\", err)\n\t} else {\n\t\tmon.SetCompleted()\n\t}\n\n\tfile, err := e.filesystem.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot open export file: %w\", err)\n\t}\n\tdefer file.Close()\n\n\t_, err = file.Write(bytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot write to export file: %w\", err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":36,"sourceCodeEnd":64,"githubUrl":"https://github.com/wagoodman/dive/blob/d6c691947f8fda635c952a17ee3b7555379d58f0/cmd/dive/cli/internal/command/adapter/exporter.go#L36-L64","documentation":"Returned when afero's OpenFile(path, O_RDWR|O_CREATE, 0644) fails while creating/truncating the export target file. The path comes directly from the --json flag (opts.Export.JsonPath). This wraps ordinary filesystem errors: a directory in the path that does not exist, permission denied, or the target being a directory.","triggerScenarios":"Running dive image --json /nonexistent-dir/report.json (parent dir missing), --json into a read-only location, --json / (path is a directory), or when the process lacks write permission on the target directory.","commonSituations":"CI pipelines writing --json into an artifact directory that the build step never created (mkdir -p forgotten); running as a user without write access to the given path; typo'd path with a missing intermediate directory.","solutions":["Check the wrapped error (the %w part) — it names the exact OS-level cause","Create the parent directory first: mkdir -p $(dirname <path>) or ensure the CI job creates the artifacts dir","Verify write permission on the target directory and that the path is not an existing directory","Use an absolute path in scripts to avoid cwd-relative surprises"],"exampleFix":"# before\ndive nginx:latest --json artifacts/report.json  # artifacts/ does not exist\n\n# after\nmkdir -p artifacts && dive nginx:latest --json artifacts/report.json","handlingStrategy":"validation","validationCode":"// ensure the parent directory and a regular-file target before exporting\nif dir := filepath.Dir(path); dir != \"\" {\n    if err := os.MkdirAll(dir, 0o755); err != nil { return err }\n}\nif fi, err := os.Stat(path); err == nil && fi.IsDir() { return fmt.Errorf(\"export path is a directory: %s\", path) }","typeGuard":null,"tryCatchPattern":"if err := exporter.ExportTo(ctx, analysis, path); err != nil {\n    if strings.Contains(err.Error(), \"cannot open export file\") {\n        // filesystem problem: check dir existence + permissions, then retry once after MkdirAll\n    }\n    return err\n}","preventionTips":["mkdir -p the export directory in CI before invoking dive","Prefer absolute paths for --json in scripts","Stat the target path early to fail before an expensive analysis runs"],"tags":["export","filesystem","permissions","path","json"],"backgroundTag":null,"analyzedSha":"d6c691947f8fda635c952a17ee3b7555379d58f0","analyzedAt":"2026-08-15T09:42:35.293Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}