{"record":{"id":"51e092131c397ff3","repo":"containerd/containerd","slug":"media-type-schema-1-not-supported","errorCode":null,"errorMessage":"media-type: schema 1 not supported","messagePattern":"media-type: schema 1 not supported","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/images/image.go","lineNumber":399,"sourceCode":"type unknownDocument struct {\n\tMediaType string          `json:\"mediaType,omitempty\"`\n\tConfig    json.RawMessage `json:\"config,omitempty\"`\n\tLayers    json.RawMessage `json:\"layers,omitempty\"`\n\tManifests json.RawMessage `json:\"manifests,omitempty\"`\n\tFSLayers  json.RawMessage `json:\"fsLayers,omitempty\"` // schema 1\n}\n\n// validateMediaType returns an error if the byte slice is invalid JSON,\n// if the format of the blob is not supported, or if the media type\n// identifies the blob as one format, but it identifies itself as, or\n// contains elements of another format.\nfunc validateMediaType(b []byte, mt string) error {\n\tvar doc unknownDocument\n\tif err := json.Unmarshal(b, &doc); err != nil {\n\t\treturn err\n\t}\n\tif len(doc.FSLayers) != 0 {\n\t\treturn fmt.Errorf(\"media-type: schema 1 not supported\")\n\t}\n\tif IsManifestType(mt) && (len(doc.Manifests) != 0 || IsIndexType(doc.MediaType)) {\n\t\treturn fmt.Errorf(\"media-type: expected manifest but found index (%s)\", mt)\n\t} else if IsIndexType(mt) && (len(doc.Config) != 0 || len(doc.Layers) != 0 || IsManifestType(doc.MediaType)) {\n\t\treturn fmt.Errorf(\"media-type: expected index but found manifest (%s)\", mt)\n\t}\n\treturn nil\n}\n\n// RootFS returns the unpacked diffids that make up and images rootfs.\n//\n// These are used to verify that a set of layers unpacked to the expected\n// values.\nfunc RootFS(ctx context.Context, provider content.Provider, configDesc ocispec.Descriptor) ([]digest.Digest, error) {\n\tp, err := content.ReadBlob(ctx, provider, configDesc)\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/containerd/containerd/blob/4246446a2bf7d03837b0244118d858799393bd80/core/images/image.go#L381-L417","documentation":"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.","triggerScenarios":"Walking/fetching an image whose blob was pushed as Docker schema 1 (application/vnd.docker.distribution.manifest.v1+prettyjws) while traversed via Children()/validateMediaType.","commonSituations":"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.","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."],"exampleFix":"// before: pulling legacy image directly\nctr images pull oldreg/app:1.0 // fails with schema 1 error\n// after: convert first\n// skopeo copy --format oci docker://oldreg/app:1.0 oci:/tmp/app:1.0\n// ctr images import /tmp/app/oci-layout","handlingStrategy":"validation","validationCode":"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\") }","typeGuard":"func isSchema1(desc ocispec.Descriptor) bool {\n\treturn desc.MediaType == images.MediaTypeDockerSchema1Manifest\n}","tryCatchPattern":"_, err := images.Children(ctx, store, desc)\nif err != nil && strings.Contains(err.Error(), \"schema 1 not supported\") {\n\treturn migrateLegacyImage(ctx, ref) // skopeo copy --format oci\n}","preventionTips":["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."],"tags":["schema1","docker","legacy","media-type"],"backgroundTag":"docker-schema1-unsupported","analyzedSha":"4246446a2bf7d03837b0244118d858799393bd80","analyzedAt":"2026-09-02T00:14:43.053Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}