{"record":{"id":"9cd3332c23e6fd6b","repo":"wagoodman/dive","slug":"cannot-export-analysis-w","errorCode":null,"errorMessage":"cannot export analysis: %w","messagePattern":"cannot export analysis: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/dive/cli/internal/command/root.go","lineNumber":82,"sourceCode":"\ttype Stater interface {\n\t\tState() *clio.State\n\t}\n\n\tstate := app.(Stater).State()\n\n\tux := ui.NewV1UI(opts.V1Preferences(), os.Stdout, state.Config.Log.Quiet, state.Config.Log.Verbosity)\n\treturn state.UI.Replace(ux)\n}\n\nfunc run(ctx context.Context, opts options.Application, img *image.Image, content image.ContentReader) error {\n\tanalysis, err := adapter.NewAnalyzer().Analyze(ctx, img)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot analyze image: %w\", err)\n\t}\n\n\tif opts.Export.JsonPath != \"\" {\n\t\tif err := adapter.NewExporter(afero.NewOsFs()).ExportTo(ctx, analysis, opts.Export.JsonPath); err != nil {\n\t\t\treturn fmt.Errorf(\"cannot export analysis: %w\", err)\n\t\t}\n\t\treturn nil\n\t}\n\n\tif opts.CI.Enabled {\n\t\teval := adapter.NewEvaluator(opts.CI.Rules.List).Evaluate(ctx, analysis)\n\n\t\tif !eval.Pass {\n\t\t\treturn errors.New(\"evaluation failed\")\n\t\t}\n\t\treturn nil\n\t}\n\n\tbus.ExploreAnalysis(*analysis, content)\n\n\treturn nil\n}\n","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/wagoodman/dive/blob/d6c691947f8fda635c952a17ee3b7555379d58f0/cmd/dive/cli/internal/command/root.go#L64-L100","documentation":"Thrown by dive's CLI root command when exporting the image analysis to a JSON file fails. The run() function has already successfully analyzed the image, then adapter.NewExporter().ExportTo() (writing via afero to opts.Export.JsonPath) returned an error. The %w chain preserves the underlying filesystem cause (permissions, unwritable path, disk full).","triggerScenarios":"Running dive with --json/-j <path> where the file cannot be created or written: unwritable directory, permission denied, read-only filesystem, path is a directory, or the process runs out of disk during write.","commonSituations":"CI pipelines writing --json output into a read-only or missing workspace directory; running as a user without write permission on the target dir; a stale --ci --json flag combination pointing at a path mounted read-only in a container.","solutions":["Check the wrapped error (dive uses %w) to see the underlying os/afero cause such as 'permission denied' or 'no such file or directory'.","Verify the directory of the --json path exists and is writable: mkdir -p $(dirname <path>) && touch <path>.","If writing to a restricted location in CI, write to a temp path first or adjust volume mounts/permissions.","Confirm the path is a file path, not an existing directory name."],"exampleFix":"# before\ndive image --json /protected/out.json   # -> cannot export analysis: open /protected/out.json: permission denied\n\n# after\nmkdir -p ./reports && dive image --json ./reports/out.json","handlingStrategy":"validation","validationCode":"// before invoking dive programmatically (or in a wrapper script):\nif dir := filepath.Dir(jsonPath); dir != \"\" {\n    if info, err := os.Stat(dir); err != nil || !info.IsDir() {\n        os.MkdirAll(dir, 0o755)\n    }\n}\n// also probe writability early:\nf, err := os.Create(jsonPath)\nif err != nil { return fmt.Errorf(\"json path unwritable: %w\", err) }\nf.Close()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pre-create and probe-writable output directories in CI before running dive --json.","Always read the wrapped error (%w) to distinguish permission vs path vs disk-full causes.","Use relative paths under the current workspace to avoid mount-permission surprises."],"tags":["dive","export","json","filesystem","cli"],"backgroundTag":null,"analyzedSha":"d6c691947f8fda635c952a17ee3b7555379d58f0","analyzedAt":"2026-08-15T09:42:35.293Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}