wagoodman/dive · error
unable to extract from image '%s': %+v
Error message
unable to extract from image '%s': %+v
What it means
Returned by engineResolver.Extract (dive/image/docker/engine_resolver.go:66) when ExtractFromImage fails for a docker-engine image. Note a defect in this region: the code shadows the error in `if err := ExtractFromImage(...); err == nil` and then formats the outer stale `err` from fetchArchive (already nil-checked), so the message's %+v detail is always '<nil>' and the real cause is lost. The failure itself still comes from ExtractFromImage (e.g. missing layer path, tar processing error, write failures to the destination).
Source
Thrown at dive/image/docker/engine_resolver.go:66
func (r *engineResolver) Build(ctx context.Context, args []string) (*image.Image, error) {
id, err := buildImageFromCli(afero.NewOsFs(), args)
if err != nil {
return nil, err
}
return r.Fetch(ctx, id)
}
func (r *engineResolver) Extract(ctx context.Context, id string, l string, p string) error {
reader, err := r.fetchArchive(ctx, id)
if err != nil {
return err
}
if err := ExtractFromImage(io.NopCloser(reader), l, p); err == nil {
return nil
}
return fmt.Errorf("unable to extract from image '%s': %+v", id, err)
}
func (r *engineResolver) fetchArchive(ctx context.Context, id string) (io.ReadCloser, error) {
var err error
var dockerClient *client.Client
host, err := determineDockerHost()
if err != nil {
return nil, fmt.Errorf("could not determine docker host: %v", err)
}
clientOpts := []client.Opt{client.FromEnv}
clientOpts = append(clientOpts, client.WithHost(host))
switch strings.Split(host, ":")[0] {
case "ssh":
helper, err := connhelper.GetConnectionHelper(host)
if err != nil {
return nil, fmt.Errorf("failed to get docker connection helper: %w", err)View on GitHub (pinned to d6c691947f)
Solutions
- Update dive - newer releases fix the error shadowing so the real cause is reported
- Sanity-check the selector against the image: confirm the layer/file path exists via the dive UI before extracting
- Check the destination: writable, not full (df -h), correct permissions
- Fall back to native tooling to confirm the data is extractable: docker save + tar -xf
Example fix
// upstream bug worth fixing if you fork dive:
// before
if err := ExtractFromImage(io.NopCloser(reader), l, p); err == nil {
return nil
}
return fmt.Errorf("unable to extract from image '%s': %+v", id, err) // err is always nil
// after
if err := ExtractFromImage(io.NopCloser(reader), l, p); err != nil {
return fmt.Errorf("unable to extract from image '%s': %w", id, err)
}
return nil Defensive patterns
Strategy: try-catch
Validate before calling
// confirm the selector matches something before extracting
// (use the dive UI/file listing to verify layer + file paths exist for the image)
exists, err := imageHasPath(img, layerPath)
if err != nil || !exists {
return fmt.Errorf("nothing to extract at %s", layerPath)
} Try / catch
err := resolver.Extract(ctx, id, layer, dest)
if err != nil {
if strings.Contains(err.Error(), "unable to extract from image") {
// note: this dive version reports <nil> detail (error-shadowing bug); diagnose independently:
// 1) dest writable? df -h dest 2) layer selector valid? 3) engine healthy? docker info
return fmt.Errorf("extract failed (cause hidden by dive bug): %w", err)
}
return err
} Prevention
- Upgrade dive - fixed releases report the real cause
- Validate destination writability and disk space before extraction
- Verify layer/file selectors against the image listing first
When it happens
Trigger: Extracting with a layer/file selector that does not match anything in the fetched archive; the engine returning an incomplete archive; destination write errors; any ExtractFromImage failure - and because of the shadowing bug you get no diagnostic detail, only the image id.
Common situations: Export workflows that pass a file filter or destination the layer doesn't contain; disk-full or permission-denied on the export directory; dive versions carrying this bug make triage hard since the cause prints as <nil>.
Related errors
AI-assisted analysis of wagoodman/dive@d6c691947f (2026-08-15).
Data as JSON: /api/errors/1ab2d05e8db19c38.
Report an issue: GitHub.