{"record":{"id":"a1a4a100f1abb0c0","repo":"apache/iceberg","slug":"cannot-convert-type-to-sql-primitive-a1a4a1","errorCode":null,"errorMessage":"Cannot convert type to SQL: <primitive>","messagePattern":"Cannot convert type to SQL: <primitive>","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java","lineNumber":644,"sourceCode":"        case DOUBLE:\n          return \"double\";\n        case DATE:\n          return \"date\";\n        case TIME:\n          return \"time\";\n        case TIMESTAMP:\n          return \"timestamp\";\n        case STRING:\n        case UUID:\n          return \"string\";\n        case FIXED:\n        case BINARY:\n          return \"binary\";\n        case DECIMAL:\n          Types.DecimalType decimal = (Types.DecimalType) primitive;\n          return \"decimal(\" + decimal.precision() + \",\" + decimal.scale() + \")\";\n      }\n      throw new UnsupportedOperationException(\"Cannot convert type to SQL: \" + primitive);\n    }\n  }\n\n  private static class DescribeExpressionVisitor\n      extends ExpressionVisitors.ExpressionVisitor<String> {\n    private static final DescribeExpressionVisitor INSTANCE = new DescribeExpressionVisitor();\n\n    private DescribeExpressionVisitor() {}\n\n    @Override\n    public String alwaysTrue() {\n      return \"true\";\n    }\n\n    @Override\n    public String alwaysFalse() {\n      return \"false\";\n    }","sourceCodeStart":626,"sourceCodeEnd":662,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java#L626-L662","documentation":"Spark3Util.primitive converts an Iceberg primitive Type into a SQL type string for DESCRIBE output. The switch covers the known primitive kinds; any primitive type not represented (e.g. newly added spec types) falls through to UnsupportedOperationException since no SQL spelling exists for it.","triggerScenarios":"DESCRIBE TABLE (or describeSpannedTable) on a table whose schema contains a primitive type not handled by the switch — typically a newer Iceberg type such as an unknown/nanoTime-like variant or future spec additions.","commonSituations":"Tables written by a newer Iceberg/spec version then inspected by an older Spark integration; custom type extensions.","solutions":["Upgrade the Iceberg Spark runtime to a version that knows the type","Rewrite the schema to use fully supported primitive types","Inspect the table with a core tool (IcebergInspect/ShowCreateTable alternatives) that handles the type"],"exampleFix":"// before\n// old runtime reading a table with a new primitive type\n// after\n// upgrade: implementation 'org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:<newer-version>'","handlingStrategy":"try-catch","validationCode":"for (Types.NestedField f : schema.columns()) {\n  if (f.type() instanceof Types.PrimitiveType) {\n    // ensure type is one of the known SQL-mappable primitives\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  spark.sql(\"DESCRIBE TABLE \" + tableName);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().startsWith(\"Cannot convert type to SQL\")) {\n    // upgrade Iceberg runtime or inspect the table with core APIs\n  }\n}","preventionTips":["Keep the Iceberg Spark runtime at or above the version that wrote the tables","Avoid custom/experimental types in shared schemas","Pin dependency versions across engines reading the same tables"],"tags":["spark","type-conversion","sql"],"backgroundTag":"type-mismatch","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}