helm/helm · error

expected config media type %s for legacy compatibility, got

Error message

expected config media type %s for legacy compatibility, got %s

What it means

Thrown by registry Client.PullPlugin (pkg/registry/plugin.go) after downloading an OCI manifest. For backwards compatibility, when a manifest has no OCI 1.1 artifactType Helm requires the manifest's config descriptor mediaType to equal PluginArtifactType (application/vnd.helm.plugin.v1+json). If the artifact has neither an artifactType nor that legacy config media type, it is not a Helm plugin and the pull is rejected.

Source

Thrown at pkg/registry/plugin.go:99

	manifestData, err := c.Generic().GetDescriptorData(genericResult.MemoryStore, genericResult.Manifest)
	if err != nil {
		return nil, fmt.Errorf("unable to retrieve manifest: %w", err)
	}

	// Parse the manifest to check artifact type
	var manifest ocispec.Manifest
	if err := json.Unmarshal(manifestData, &manifest); err != nil {
		return nil, fmt.Errorf("unable to parse manifest: %w", err)
	}

	// Validate artifact type (for OCI v1.1+ manifests)
	if manifest.ArtifactType != "" && manifest.ArtifactType != PluginArtifactType {
		return nil, fmt.Errorf("expected artifact type %s, got %s", PluginArtifactType, manifest.ArtifactType)
	}

	// For backwards compatibility, also check config media type if no artifact type
	if manifest.ArtifactType == "" && manifest.Config.MediaType != PluginArtifactType {
		return nil, fmt.Errorf("expected config media type %s for legacy compatibility, got %s", PluginArtifactType, manifest.Config.MediaType)
	}

	// Find the plugin tarball and optional provenance using NAME-VERSION.tgz format
	var pluginDescriptor *ocispec.Descriptor
	var provenanceDescriptor *ocispec.Descriptor
	var foundProvenanceName string

	// Look for layers with the expected titles/annotations
	for _, layer := range manifest.Layers {
		d := layer
		// Check for title annotation
		if title, exists := d.Annotations[ocispec.AnnotationTitle]; exists {
			// Check if this looks like a plugin tarball: {pluginName}-{version}.tgz
			if pluginDescriptor == nil && strings.HasPrefix(title, pluginName+"-") && strings.HasSuffix(title, ".tgz") {
				pluginDescriptor = &d
			}
			// Check if this looks like a plugin provenance: {pluginName}-{version}.tgz.prov
			if provenanceDescriptor == nil && strings.HasPrefix(title, pluginName+"-") && strings.HasSuffix(title, ".tgz.prov") {

View on GitHub (pinned to 2a29f1770b)

Solutions

  1. Inspect the artifact: `crane manifest <ref>` and check artifactType and config.mediaType fields
  2. Confirm the ref is a plugin artifact, not a chart; charts are pulled with `helm pull oci://...` not `helm plugin pull`
  3. Re-push the plugin with `helm plugin push`, which sets the correct artifact/config media type
  4. If pushing manually with oras, set --artifact-type application/vnd.helm.plugin.v1+json (or the config media type to the same value)

Example fix

# before (fails: chart artifact has no plugin config media type)
helm plugin pull oci://ghcr.io/user/mychart:1.0.0

# after (plugin artifact pushed with: helm plugin push ./my-plugin oci://ghcr.io/user/my-plugin)
helm plugin pull oci://ghcr.io/user/my-plugin:1.0.0
Defensive patterns

Strategy: try-catch

Try / catch

res, err := client.PullPlugin(ref, pluginName)
if err != nil {
	msg := err.Error()
	if strings.Contains(msg, "expected config media type") || strings.Contains(msg, "expected artifact type") {
		// ref is not a Helm plugin artifact - route to chart pull or reject the input
		return fmt.Errorf("%s is not a plugin artifact", ref)
	}
	return err
}

Prevention

When it happens

Trigger: Calling Client.PullPlugin or `helm plugin pull`/`helm plugin install` from an oci:// ref whose manifest omits artifactType and whose config.mediaType is different, e.g. a Helm chart pushed with `helm push` (config media type application/vnd.cncf.helm.config.v1+json), a plain OCI image, or an artifact pushed with oras without the plugin config type.

Common situations: Pointing a plugin pull at a chart OCI ref instead of a plugin ref; plugins pushed with custom tooling that set a different config media type; automation scripts that mix chart and plugin references; artifacts pushed before the plugin artifact-type convention existed.

Related errors


AI-assisted analysis of helm/helm@2a29f1770b (2026-08-15). Data as JSON: /api/errors/e93700ef4c35574b. Report an issue: GitHub.