containerd/containerd · error
media-type: schema 1 not supported
Error message
media-type: schema 1 not supported
What it means
validateMediaType rejects blobs containing an fsLayers field with "media-type: schema 1 not supported". Docker schema 1 manifests (pre-2017 format) are explicitly unsupported by containerd's image walk/children traversal.
Source
Thrown at core/images/image.go:399
type unknownDocument struct {
MediaType string `json:"mediaType,omitempty"`
Config json.RawMessage `json:"config,omitempty"`
Layers json.RawMessage `json:"layers,omitempty"`
Manifests json.RawMessage `json:"manifests,omitempty"`
FSLayers json.RawMessage `json:"fsLayers,omitempty"` // schema 1
}
// validateMediaType returns an error if the byte slice is invalid JSON,
// if the format of the blob is not supported, or if the media type
// identifies the blob as one format, but it identifies itself as, or
// contains elements of another format.
func validateMediaType(b []byte, mt string) error {
var doc unknownDocument
if err := json.Unmarshal(b, &doc); err != nil {
return err
}
if len(doc.FSLayers) != 0 {
return fmt.Errorf("media-type: schema 1 not supported")
}
if IsManifestType(mt) && (len(doc.Manifests) != 0 || IsIndexType(doc.MediaType)) {
return fmt.Errorf("media-type: expected manifest but found index (%s)", mt)
} else if IsIndexType(mt) && (len(doc.Config) != 0 || len(doc.Layers) != 0 || IsManifestType(doc.MediaType)) {
return fmt.Errorf("media-type: expected index but found manifest (%s)", mt)
}
return nil
}
// RootFS returns the unpacked diffids that make up and images rootfs.
//
// These are used to verify that a set of layers unpacked to the expected
// values.
func RootFS(ctx context.Context, provider content.Provider, configDesc ocispec.Descriptor) ([]digest.Digest, error) {
p, err := content.ReadBlob(ctx, provider, configDesc)
if err != nil {
return nil, err
}View on GitHub (pinned to 4246446a2b)
Solutions
- Rebuild/re-push the image so it produces a schema 2 or OCI manifest (docker build + modern push, or buildkit).
- Use `docker save`/`skopeo copy --format oci` to convert legacy image tarballs before importing.
- If the registry still serves schema 1, configure the Docker client to request schema 2 (DOCKER_NOW_TLS... no — set Accept headers via a modern puller) or upgrade the registry.
- Migrate legacy registries with skopeo sync to regenerate manifest format.
Example fix
// before: pulling legacy image directly ctr images pull oldreg/app:1.0 // fails with schema 1 error // after: convert first // skopeo copy --format oci docker://oldreg/app:1.0 oci:/tmp/app:1.0 // ctr images import /tmp/app/oci-layout
Defensive patterns
Strategy: validation
Validate before calling
ra, _ := cs.ReaderAt(ctx, desc); blob := make([]byte, ra.Size()); ra.ReadAt(blob, 0); if bytes.Contains(blob, []byte("fsLayers")) { return errors.New("schema 1 image; migrate first") } Type guard
func isSchema1(desc ocispec.Descriptor) bool {
return desc.MediaType == images.MediaTypeDockerSchema1Manifest
} Try / catch
_, err := images.Children(ctx, store, desc)
if err != nil && strings.Contains(err.Error(), "schema 1 not supported") {
return migrateLegacyImage(ctx, ref) // skopeo copy --format oci
} Prevention
- Audit private registries for schema 1 images and re-push them in schema 2/OCI format.
- Convert legacy docker save tarballs with skopeo before importing into containerd.
- Upgrade any pre-2017 registry software still serving schema 1 manifests.
When it happens
Trigger: Walking/fetching an image whose blob was pushed as Docker schema 1 (application/vnd.docker.distribution.manifest.v1+prettyjws) while traversed via Children()/validateMediaType.
Common situations: Images from legacy private registries (old Harbor/docker registry) never re-pushed; cached blobs from pre-2017 images; vendored image tarballs exported from very old Docker daemons.
Related errors
- %v not supported
- no processor for media-type
- failed to get stream processor for %s: %w
- failed to detect media type of layer: %w
- manifest: invalid desc %s: %w
AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02).
Data as JSON: /api/errors/51e092131c397ff3.
Report an issue: GitHub.