wagoodman/dive · error
cannot export analysis: %w
Error message
cannot export analysis: %w
What it means
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).
Source
Thrown at cmd/dive/cli/internal/command/root.go:82
type Stater interface {
State() *clio.State
}
state := app.(Stater).State()
ux := ui.NewV1UI(opts.V1Preferences(), os.Stdout, state.Config.Log.Quiet, state.Config.Log.Verbosity)
return state.UI.Replace(ux)
}
func run(ctx context.Context, opts options.Application, img *image.Image, content image.ContentReader) error {
analysis, err := adapter.NewAnalyzer().Analyze(ctx, img)
if err != nil {
return fmt.Errorf("cannot analyze image: %w", err)
}
if opts.Export.JsonPath != "" {
if err := adapter.NewExporter(afero.NewOsFs()).ExportTo(ctx, analysis, opts.Export.JsonPath); err != nil {
return fmt.Errorf("cannot export analysis: %w", err)
}
return nil
}
if opts.CI.Enabled {
eval := adapter.NewEvaluator(opts.CI.Rules.List).Evaluate(ctx, analysis)
if !eval.Pass {
return errors.New("evaluation failed")
}
return nil
}
bus.ExploreAnalysis(*analysis, content)
return nil
}
View on GitHub (pinned to d6c691947f)
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.
Example fix
# before dive image --json /protected/out.json # -> cannot export analysis: open /protected/out.json: permission denied # after mkdir -p ./reports && dive image --json ./reports/out.json
Defensive patterns
Strategy: validation
Validate before calling
// before invoking dive programmatically (or in a wrapper script):
if dir := filepath.Dir(jsonPath); dir != "" {
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
os.MkdirAll(dir, 0o755)
}
}
// also probe writability early:
f, err := os.Create(jsonPath)
if err != nil { return fmt.Errorf("json path unwritable: %w", err) }
f.Close() Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- directory for JSON export does not exist: %s
- cannot open export file: %w
- cannot write to export file: %w
- cannot marshal export payload: %w
- unable to determine image source from %q: %v
AI-assisted analysis of wagoodman/dive@d6c691947f (2026-08-15).
Data as JSON: /api/errors/9cd3332c23e6fd6b.
Report an issue: GitHub.