{"record":{"id":"97bfa89d6c5fa85d","repo":"apache/iceberg","slug":"orc-schema-does-not-contain-iceberg-ids","errorCode":null,"errorMessage":"ORC schema does not contain Iceberg IDs","messagePattern":"ORC schema does not contain Iceberg IDs","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"orc/src/main/java/org/apache/iceberg/orc/ORCSchemaUtil.java","lineNumber":293,"sourceCode":"   * @return the Iceberg schema\n   * @throws IllegalArgumentException if ORC schema has no columns with Iceberg ID attributes\n   */\n  public static Schema convert(TypeDescription orcSchema) {\n    List<TypeDescription> children = orcSchema.getChildren();\n    List<String> childrenNames = orcSchema.getFieldNames();\n    Preconditions.checkState(\n        children.size() == childrenNames.size(),\n        \"Error in ORC file, children fields and names do not match.\");\n\n    OrcToIcebergVisitor schemaConverter = new OrcToIcebergVisitor();\n    List<Types.NestedField> fields =\n        OrcToIcebergVisitor.visitSchema(orcSchema, schemaConverter).stream()\n            .filter(Optional::isPresent)\n            .map(Optional::get)\n            .collect(Collectors.toList());\n\n    if (fields.isEmpty()) {\n      throw new IllegalArgumentException(\"ORC schema does not contain Iceberg IDs\");\n    }\n\n    return new Schema(fields);\n  }\n\n  /**\n   * Converts an Iceberg schema to a corresponding ORC schema within the context of an existing ORC\n   * file schema. This method also handles schema evolution from the original ORC file schema to the\n   * given Iceberg schema. It builds the desired reader schema with the schema evolution rules and\n   * pass that down to the ORC reader, which would then use its schema evolution to map that to the\n   * writer’s schema.\n   *\n   * <p>Example: <code>\n   * Iceberg writer                                        ORC writer\n   * struct&lt;a (1): int, b (2): string&gt;                     struct&lt;a: int, b: string&gt;\n   * struct&lt;a (1): struct&lt;b (2): string, c (3): date&gt;&gt;     struct&lt;a: struct&lt;b:string, c:date&gt;&gt;\n   * </code> Iceberg reader ORC reader <code>\n   * struct&lt;a (2): string, c (3): date&gt;                    struct&lt;b: string, c: date&gt;","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/orc/src/main/java/org/apache/iceberg/orc/ORCSchemaUtil.java#L275-L311","documentation":"When converting an existing ORC file schema back into an Iceberg Schema, Iceberg IDs are recovered from ORC column attributes (iceberg.id). If, after visiting the whole ORC schema, no field carries those attributes, the resulting field list is empty and IllegalArgumentException is thrown. This protects against silently producing an empty schema for a non-Iceberg-written ORC file.","triggerScenarios":"Calling ORCSchemaUtil.convert(orcSchema) (schema conversion from ORC to Iceberg) on an ORC file whose TypeDescription attributes lack the Iceberg ID attribute — i.e. the file was not written by Iceberg's ORC writer or the attributes were stripped.","commonSituations":"Pointing Iceberg at ORC files written by other tools (Hive/Spark raw ORC, Trino); files rewritten or copied with an ORC library that drops custom attributes; older Iceberg-written files predating the ID attribute convention.","solutions":["Rewrite the data with Iceberg's ORC writer so iceberg.id attributes are stamped into the ORC schema.","If consuming external ORC files, provide an explicit Iceberg schema / name mapping (e.g. via name-mapping) instead of inferring one from the ORC schema.","Verify the file was produced by the same Iceberg version lineage that sets ORC column attributes; re-export if the attributes are missing."],"exampleFix":"// before (inferring schema from external ORC file)\nSchema schema = ORCSchemaUtil.convert(orcReader.getSchema()); // IllegalArgumentException\n\n// after (supply explicit schema / name mapping instead)\nSchema schema = new Schema(\n    Types.NestedField.required(1, \"id\", Types.LongType.get()),\n    Types.NestedField.optional(2, \"data\", Types.StringType.get()));","handlingStrategy":"validation","validationCode":"TypeDescription orcSchema = orcReader.getSchema();\nboolean hasIds = orcSchema.getChildren().stream()\n    .anyMatch(t -> t.getAttributeValue(\"iceberg.id\") != null);\nif (!hasIds) {\n  throw new IllegalStateException(\"ORC file lacks Iceberg ID attributes; supply an explicit schema\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  Schema s = ORCSchemaUtil.convert(orcSchema);\n} catch (IllegalArgumentException e) {\n  // fall back to externally provided schema\n}","preventionTips":["Only infer Iceberg schemas from ORC files written by Iceberg's ORC writer","Provide an explicit schema or name mapping for external ORC files","Avoid tools/copies that strip ORC custom column attributes"],"tags":["java","orc","schema","metadata"],"backgroundTag":"schema-validation-failed","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"}