{"record":{"id":"3e7596e5fd78d4fe","repo":"apache/iceberg","slug":"reader-does-not-support-metadata-reading-s","errorCode":null,"errorMessage":"Reader does not support metadata reading: %s","messagePattern":"Reader does not support metadata reading: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/ManifestReader.java","lineNumber":197,"sourceCode":"    return PartitionSpecParser.fromJsonFields(schema, specId, metadata.get(\"partition-spec\"));\n  }\n\n  private static <T extends ContentFile<T>> Map<String, String> readMetadata(InputFile inputFile) {\n    FileFormat manifestFormat = FileFormat.fromFileName(inputFile.location());\n    Preconditions.checkArgument(\n        manifestFormat == FileFormat.AVRO,\n        \"Reading manifest metadata is only supported for Avro manifests: %s\",\n        inputFile.location());\n\n    Map<String, String> metadata;\n    try {\n      try (CloseableIterable<ManifestEntry<T>> headerReader =\n          InternalData.read(FileFormat.AVRO, inputFile).project(STATUS_ONLY_PROJECTION).build()) {\n\n        if (headerReader instanceof AvroIterable) {\n          metadata = ((AvroIterable<ManifestEntry<T>>) headerReader).getMetadata();\n        } else {\n          throw new RuntimeException(\n              \"Reader does not support metadata reading: \" + headerReader.getClass().getName());\n        }\n      }\n    } catch (IOException e) {\n      throw new RuntimeIOException(e);\n    }\n    return metadata;\n  }\n\n  public boolean isDeleteManifestReader() {\n    return content == FileType.DELETE_FILES;\n  }\n\n  public InputFile file() {\n    return file;\n  }\n\n  public Schema schema() {","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/ManifestReader.java#L179-L215","documentation":"ManifestReader.readMetadata expects the iterable produced by InternalData.read(...) to be an AvroIterable exposing file-level metadata; if the reader implementation is a different class it cannot supply metadata, so a plain RuntimeException is thrown naming the reader class. This guards an internal assumption that manifest files are Avro.","triggerScenarios":"Calling ManifestReader.metadata() (or read in a way that triggers readMetadata) on a file whose data reader is not an AvroIterable — e.g., a custom InternalData/FileIO reader plugged in, or a manifest file in an unexpected format.","commonSituations":"Custom FileIO/data implementations returning non-Avro readers; plugging experimental file formats into InternalData; unit-test stubs returning generic CloseableIterable instead of AvroIterable.","solutions":["Ensure manifest files are read with the default InternalData.read(FileFormat.AVRO, ...) path.","Check any custom InternalData/FileIO reader registration that changes the returned iterable class.","Remove or fix test doubles that return non-AvroIterable implementations.","Verify the file is actually an Iceberg Avro manifest and not a foreign or corrupted format."],"exampleFix":"// before: stub returning plain iterable in tests\nwhen(data.read(any(), any())).thenReturn(CloseableIterable.withNoopClose(List.of()));\n// after: return an AvroIterable-compatible stub or use a real test manifest file\nAvroIterable<ManifestEntry<DataFile>> it = Avro.read(file).project(STATUS_ONLY_PROJECTION).build();\nwhen(data.read(any(), any())).thenReturn(it);","handlingStrategy":"type-guard","validationCode":"if (!(iterable instanceof AvroIterable)) {\n  throw new IllegalStateException(\"Expected AvroIterable from InternalData.read, got \" + iterable.getClass());\n}","typeGuard":"static boolean isAvroIterable(CloseableIterable<?> it) {\n  return it instanceof AvroIterable;\n}","tryCatchPattern":"try {\n  Map<String, String> meta = ManifestFiles.read(manifest, io).metadata();\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"does not support metadata reading\")) {\n    // fall back to re-reading with the default Avro path\n  }\n}","preventionTips":["Use the stock InternalData/ManifestFiles read paths","Don't stub InternalData.read with non-Avro iterables in tests","Confirm custom FileIO doesn't replace the Avro reader factory"],"tags":["avro","manifest","internal","type-mismatch"],"backgroundTag":"unexpected-response-shape","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}