{"record":{"id":"1ab2d05e8db19c38","repo":"wagoodman/dive","slug":"unable-to-extract-from-image-s-v","errorCode":null,"errorMessage":"unable to extract from image '%s': %+v","messagePattern":"unable to extract from image '(.+?)': %\\+v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dive/image/docker/engine_resolver.go","lineNumber":66,"sourceCode":"func (r *engineResolver) Build(ctx context.Context, args []string) (*image.Image, error) {\n\tid, err := buildImageFromCli(afero.NewOsFs(), args)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn r.Fetch(ctx, id)\n}\n\nfunc (r *engineResolver) Extract(ctx context.Context, id string, l string, p string) error {\n\treader, err := r.fetchArchive(ctx, id)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := ExtractFromImage(io.NopCloser(reader), l, p); err == nil {\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"unable to extract from image '%s': %+v\", id, err)\n}\n\nfunc (r *engineResolver) fetchArchive(ctx context.Context, id string) (io.ReadCloser, error) {\n\tvar err error\n\tvar dockerClient *client.Client\n\n\thost, err := determineDockerHost()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not determine docker host: %v\", err)\n\t}\n\tclientOpts := []client.Opt{client.FromEnv}\n\tclientOpts = append(clientOpts, client.WithHost(host))\n\n\tswitch strings.Split(host, \":\")[0] {\n\tcase \"ssh\":\n\t\thelper, err := connhelper.GetConnectionHelper(host)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to get docker connection helper: %w\", err)","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/wagoodman/dive/blob/d6c691947f8fda635c952a17ee3b7555379d58f0/dive/image/docker/engine_resolver.go#L48-L84","documentation":"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).","triggerScenarios":"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.","commonSituations":"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>.","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"],"exampleFix":"// upstream bug worth fixing if you fork dive:\n// before\nif err := ExtractFromImage(io.NopCloser(reader), l, p); err == nil {\n    return nil\n}\nreturn fmt.Errorf(\"unable to extract from image '%s': %+v\", id, err) // err is always nil\n\n// after\nif err := ExtractFromImage(io.NopCloser(reader), l, p); err != nil {\n    return fmt.Errorf(\"unable to extract from image '%s': %w\", id, err)\n}\nreturn nil","handlingStrategy":"try-catch","validationCode":"// confirm the selector matches something before extracting\n// (use the dive UI/file listing to verify layer + file paths exist for the image)\nexists, err := imageHasPath(img, layerPath)\nif err != nil || !exists {\n    return fmt.Errorf(\"nothing to extract at %s\", layerPath)\n}","typeGuard":null,"tryCatchPattern":"err := resolver.Extract(ctx, id, layer, dest)\nif err != nil {\n    if strings.Contains(err.Error(), \"unable to extract from image\") {\n        // note: this dive version reports <nil> detail (error-shadowing bug); diagnose independently:\n        // 1) dest writable? df -h dest  2) layer selector valid? 3) engine healthy? docker info\n        return fmt.Errorf(\"extract failed (cause hidden by dive bug): %w\", err)\n    }\n    return err\n}","preventionTips":["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"],"tags":["docker-engine","extract","error-masking","layers"],"backgroundTag":null,"analyzedSha":"d6c691947f8fda635c952a17ee3b7555379d58f0","analyzedAt":"2026-08-15T09:42:35.293Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}