{"record":{"id":"ac00fff53e18865f","repo":"helm/helm","slug":"unable-to-retrieve-manifest-w","errorCode":null,"errorMessage":"unable to retrieve manifest: %w","messagePattern":"unable to retrieve manifest: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/registry/plugin.go","lineNumber":83,"sourceCode":"\t\t\tocispec.MediaTypeImageManifest,\n\t\t\t\"application/vnd.oci.image.layer.v1.tar\",\n\t\t\t\"application/vnd.oci.image.layer.v1.tar+gzip\",\n\t\t},\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Process the result with plugin-specific logic\n\treturn c.processPluginPull(genericResult, operation.pluginName)\n}\n\n// processPluginPull handles plugin-specific processing of a generic pull result using artifact type\nfunc (c *Client) processPluginPull(genericResult *GenericPullResult, pluginName string) (*PluginPullResult, error) {\n\t// First validate that this is actually a plugin artifact\n\tmanifestData, err := c.Generic().GetDescriptorData(genericResult.MemoryStore, genericResult.Manifest)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to retrieve manifest: %w\", err)\n\t}\n\n\t// Parse the manifest to check artifact type\n\tvar manifest ocispec.Manifest\n\tif err := json.Unmarshal(manifestData, &manifest); err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to parse manifest: %w\", err)\n\t}\n\n\t// Validate artifact type (for OCI v1.1+ manifests)\n\tif manifest.ArtifactType != \"\" && manifest.ArtifactType != PluginArtifactType {\n\t\treturn nil, fmt.Errorf(\"expected artifact type %s, got %s\", PluginArtifactType, manifest.ArtifactType)\n\t}\n\n\t// For backwards compatibility, also check config media type if no artifact type\n\tif manifest.ArtifactType == \"\" && manifest.Config.MediaType != PluginArtifactType {\n\t\treturn nil, fmt.Errorf(\"expected config media type %s for legacy compatibility, got %s\", PluginArtifactType, manifest.Config.MediaType)\n\t}\n","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/helm/helm/blob/2a29f1770b62844b27197d2507377361d45ad7c0/pkg/registry/plugin.go#L65-L101","documentation":"Client.PullPlugin fetches the artifact, then reads the manifest blob to validate its artifact type; if GetDescriptorData for the manifest descriptor fails it wraps the cause as \"unable to retrieve manifest\". The manifest bytes were unreadable — missing blob, corrupt transfer, or fetch error.","triggerScenarios":"registry.Client.PullPlugin / `helm plugin pull` where the manifest blob cannot be read after the generic pull: registry GC removed it, an interrupted upload left a dangling reference, or a network failure mid-pull.","commonSituations":"Registry garbage collection between push and pull; plugins partially uploaded by CI; unreliable mirrors.","solutions":["Retry the pull once","Inspect the reference with `crane manifest <ref>` to see whether the manifest blob resolves","Re-push the plugin artifact if the blob is genuinely missing from the registry"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"var res *registry.PluginPullResult\nerr := retry(3, time.Second, func() error {\n\tvar e error\n\tres, e = client.PullPlugin(ref, name)\n\tif e != nil && strings.Contains(e.Error(), \"unable to retrieve manifest\") {\n\t\treturn e // retryable\n\t}\n\treturn e\n})","preventionTips":["Retry plugin pulls once or twice before investigating the registry","Verify plugin artifacts with `crane manifest` right after publishing so dangling refs are caught early"],"tags":["oci","plugin","manifest","pull","blob"],"backgroundTag":null,"analyzedSha":"2a29f1770b62844b27197d2507377361d45ad7c0","analyzedAt":"2026-08-15T22:02:47.490Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}