{"record":{"id":"6dcdaf3bb2ec5357","repo":"apache/iceberg","slug":"cannot-parse-type-string-variant-is-not-a-primiti","errorCode":null,"errorMessage":"Cannot parse type string: variant is not a primitive type","messagePattern":"Cannot parse type string: variant is not a primitive type","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/types/Types.java","lineNumber":115,"sourceCode":"    if (fixed.matches()) {\n      return FixedType.ofLength(Integer.parseInt(fixed.group(1)));\n    }\n\n    Matcher decimal = DECIMAL.matcher(lowerTypeString);\n    if (decimal.matches()) {\n      return DecimalType.of(Integer.parseInt(decimal.group(1)), Integer.parseInt(decimal.group(2)));\n    }\n\n    throw new IllegalArgumentException(\"Cannot parse type string to primitive: \" + typeString);\n  }\n\n  public static PrimitiveType fromPrimitiveString(String typeString) {\n    Type type = fromTypeName(typeString);\n    if (type.isPrimitiveType()) {\n      return type.asPrimitiveType();\n    }\n\n    throw new IllegalArgumentException(\"Cannot parse type string: variant is not a primitive type\");\n  }\n\n  public static class BooleanType extends PrimitiveType {\n    private static final BooleanType INSTANCE = new BooleanType();\n\n    public static BooleanType get() {\n      return INSTANCE;\n    }\n\n    @Override\n    public TypeID typeId() {\n      return TypeID.BOOLEAN;\n    }\n\n    @Override\n    public String toString() {\n      return \"boolean\";\n    }","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/types/Types.java#L97-L133","documentation":"Thrown by Types.fromPrimitiveString when fromTypeName successfully parsed the string but the result is a nested (non-primitive) type. fromPrimitiveString only accepts primitive types; note the hardcoded message mentions 'variant' because VariantType is the notable nested type reachable via a plain name lookup.","triggerScenarios":"Calling Types.fromPrimitiveString(\"variant\") (or any type name that maps to a nested type such as a list/map/struct identifier) — the string parses fine but is not a PrimitiveType.","commonSituations":"Code that assumes a column is primitive (e.g. building predicates or ID-to-type maps) encountering a variant or other nested column type defined in the schema.","solutions":["Use Types.fromTypeName instead if nested types are acceptable","Verify the column's type is primitive before requesting a PrimitiveType (check typeID, e.g. VariantType.typeId() == Variant)","Handle variant columns separately from primitive columns in your logic"],"exampleFix":"// before\nPrimitiveType p = Types.fromPrimitiveString(\"variant\");\n// after\nType t = Types.fromTypeName(\"variant\");\nif (t.isPrimitiveType()) {\n  PrimitiveType p = t.asPrimitiveType();\n}","handlingStrategy":"type-guard","validationCode":"Type t = Types.fromTypeName(typeString);\nif (!t.isPrimitiveType()) { throw new IllegalArgumentException(\"Expected primitive type, got: \" + t); }","typeGuard":"PrimitiveType asPrimitiveOrNull(String typeString) {\n  Type t = Types.fromTypeName(typeString);\n  return t.isPrimitiveType() ? t.asPrimitiveType() : null;\n}","tryCatchPattern":"try {\n  PrimitiveType p = Types.fromPrimitiveString(typeString);\n} catch (IllegalArgumentException e) {\n  // handle nested type: fall back to Types.fromTypeName and branch on nested types\n}","preventionTips":["Check type.isPrimitiveType() when handling unknown column types","Treat variant, struct, list, and map columns in a separate code path","Prefer Types.fromTypeName when nested types are acceptable"],"tags":["java","type-parsing","type-mismatch","variant"],"backgroundTag":"type-mismatch","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"}