{"record":{"id":"0ffa72e48d5439a6","repo":"docker/compose","slug":"failed-to-pull-oci-resource-q-w","errorCode":null,"errorMessage":"failed to pull OCI resource %q: %w","messagePattern":"failed to pull OCI resource %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/remote/oci.go","lineNumber":141,"sourceCode":"\t\treturn \"\", fmt.Errorf(\"OCI remote resource is disabled by %q\", OCI_REMOTE_ENABLED)\n\t}\n\n\tif g.offline {\n\t\treturn \"\", nil\n\t}\n\n\tlocal, ok := g.known[path]\n\tif !ok {\n\t\tref, err := reference.ParseDockerRef(path[len(OciPrefix):])\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\n\t\tresolver := oci.NewResolver(g.dockerCli.ConfigFile(), g.httpTransport(ctx), g.insecureRegistries...)\n\n\t\tdescriptor, content, err := oci.Get(ctx, resolver, ref)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to pull OCI resource %q: %w\", ref, err)\n\t\t}\n\n\t\tcache, err := cacheDir()\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"initializing remote resource cache: %w\", err)\n\t\t}\n\n\t\tlocal = filepath.Join(cache, descriptor.Digest.Hex())\n\t\tif _, err = os.Stat(local); os.IsNotExist(err) {\n\n\t\t\t// a Compose application bundle is published as an image index\n\t\t\tif images.IsIndexType(descriptor.MediaType) {\n\t\t\t\tvar index spec.Index\n\t\t\t\terr = json.Unmarshal(content, &index)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn \"\", err\n\t\t\t\t}\n\t\t\t\tfound := false","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/pkg/remote/oci.go#L123-L159","documentation":"After the reference is parsed, the loader contacts the registry through oci.Get(resolver, ref) to fetch the image descriptor. Any failure at the network, authentication, or manifest-resolution level is wrapped into this message, including the offending reference for context. The underlying %w error carries the registry-specific detail (401, 404, DNS, TLS, timeout).","triggerScenarios":"Load() on an oci:// path where reference.ParseDockerRef succeeded but oci.Get failed: unknown repository/tag (manifest unknown), missing/not-logged-in registry credentials from g.dockerCli.ConfigFile(), unreachable registry, TLS failure for a registry not listed in g.insecureRegistries, or cancelled context.","commonSituations":"Forgetting `docker login registry.example.com` before referencing a private bundle; typo in the tag; corporate proxy blocking the registry; self-signed registry used without adding it to insecure registries; expired token or expired pull credentials.","solutions":["Read the wrapped error: a 401/403 means auth — run `docker login <registry>` with an account that has pull access, then retry.","A 404 / manifest-unknown means the ref is wrong — verify repository name and tag with `docker manifest inspect <ref>` or in the registry UI.","For network/TLS issues check connectivity (`curl -v https://<registry>/v2/`), proxies, and if the registry is self-signed configure it as insecure so the resolver skips verification.","Retry once if the failure is a transient timeout or DNS blip."],"exampleFix":"# before\ndocker compose -f oci://registry.example.com/mybundle:latest up\n# after (authenticate and verify the ref exists)\ndocker login registry.example.com\ndocker manifest inspect registry.example.com/mybundle:latest\ndocker compose -f oci://registry.example.com/mybundle:latest up","handlingStrategy":"retry","validationCode":"// verify ref parses and registry is reachable before Load\nif _, err := reference.ParseDockerRef(strings.TrimPrefix(path, \"oci://\")); err != nil {\n    return err // bad reference, fail before any network call\n}\nresp, err := http.Head(fmt.Sprintf(\"https://%s/v2/\", reference.Domain(ref)))\nif err != nil || resp.StatusCode >= 500 { /* expect transient failures, plan a retry */ }","typeGuard":null,"tryCatchPattern":"content, err := loader.Load(ctx, path)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to pull OCI resource\") {\n        var inner = errors.Unwrap(err)\n        if isTransient(inner) { // timeout, 5xx, EOF\n            // exponential backoff retry, e.g. 3 attempts\n        }\n        if isAuthError(inner) { // 401/403: prompt login, do not retry\n            return fmt.Errorf(\"run docker login %s: %w\", reference.Domain(ref), err)\n        }\n    }\n    return err\n}","preventionTips":["Run docker login against the registry before any compose command using oci:// paths.","Pin digests (oci://reg/repo@sha256:...) in production so tags cannot dangle.","Wrap registry interactions in retry-with-backoff for transient 5xx/timeouts."],"tags":["go","docker-compose","oci","registry","network","authentication"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}