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

  1. Check the wrapped error (dive uses %w) to see the underlying os/afero cause such as 'permission denied' or 'no such file or directory'.
  2. Verify the directory of the --json path exists and is writable: mkdir -p $(dirname <path>) && touch <path>.
  3. If writing to a restricted location in CI, write to a temp path first or adjust volume mounts/permissions.
  4. 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

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


AI-assisted analysis of wagoodman/dive@d6c691947f (2026-08-15). Data as JSON: /api/errors/9cd3332c23e6fd6b. Report an issue: GitHub.