From d7814e4421816dd20679b1b6aee67b5b262aca60 Mon Sep 17 00:00:00 2001 From: Mark Baseggio Date: Wed, 29 Oct 2025 04:46:16 -0400 Subject: [PATCH] Make Index.mediaType optional to comply with OCI spec (#368) The `mediaType` field in the `Index` struct was defined as a required field, but according to the [OCI Image Index Specification](https://github.com/opencontainers/image-spec/blob/main/image-index.md), this field is optional. This caused failures when loading OCI archives where the `index.json` omits the top-level `mediaType` field, which is valid per the spec. Tools like skopeo can generate such archives. ## Error before fix ``` keyNotFound(CodingKeys(stringValue: "mediaType", intValue: nil)) ``` ## Changes - Changed `Index.mediaType` from `String` to `String?` - Updated initializer to accept optional `mediaType` parameter - Added comment documenting that field is optional per OCI spec ## Testing Verified that OCI archives without a top-level `mediaType` field in `index.json` now load successfully. Fixes https://github.com/apple/container/issues/330 --- Sources/ContainerizationOCI/Index.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Sources/ContainerizationOCI/Index.swift b/Sources/ContainerizationOCI/Index.swift index 3aee6eb4..7de9fba2 100644 --- a/Sources/ContainerizationOCI/Index.swift +++ b/Sources/ContainerizationOCI/Index.swift @@ -25,6 +25,7 @@ public struct Index: Codable, Sendable { public let schemaVersion: Int /// mediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json` + /// This field is optional per the OCI Image Index Specification (omitempty) public let mediaType: String /// manifests references platform specific manifests. @@ -42,4 +43,12 @@ public struct Index: Codable, Sendable { self.manifests = manifests self.annotations = annotations } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.schemaVersion = try container.decode(Int.self, forKey: .schemaVersion) + self.mediaType = try container.decodeIfPresent(String.self, forKey: .mediaType) ?? "" + self.manifests = try container.decode([Descriptor].self, forKey: .manifests) + self.annotations = try container.decodeIfPresent([String: String].self, forKey: .annotations) + } }