{"record":{"id":"bdec35966ec8e31e","repo":"apache/iceberg","slug":"cannot-convert-spark-geometry-with-mixed-srid-to-i-bdec35","errorCode":null,"errorMessage":"Cannot convert Spark geometry with mixed SRID to Iceberg","messagePattern":"Cannot convert Spark geometry with mixed SRID to Iceberg","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkTypeToType.java","lineNumber":173,"sourceCode":"\n    } else if (atomic instanceof DateType) {\n      return Types.DateType.get();\n\n    } else if (atomic instanceof TimestampType) {\n      return Types.TimestampType.withZone();\n\n    } else if (atomic instanceof TimestampNTZType) {\n      return Types.TimestampType.withoutZone();\n\n    } else if (atomic instanceof DecimalType) {\n      return Types.DecimalType.of(\n          ((DecimalType) atomic).precision(), ((DecimalType) atomic).scale());\n    } else if (atomic instanceof BinaryType) {\n      return Types.BinaryType.get();\n    } else if (atomic instanceof GeometryType) {\n      GeometryType geometry = (GeometryType) atomic;\n      if (geometry.isMixedSrid()) {\n        throw new UnsupportedOperationException(\n            \"Cannot convert Spark geometry with mixed SRID to Iceberg\");\n      }\n      return Types.GeometryType.of(geometry.crs());\n    } else if (atomic instanceof GeographyType) {\n      GeographyType geography = (GeographyType) atomic;\n      if (geography.isMixedSrid()) {\n        throw new UnsupportedOperationException(\n            \"Cannot convert Spark geography with mixed SRID to Iceberg\");\n      }\n      return Types.GeographyType.of(geography.crs(), convertAlgorithm(geography.algorithm()));\n    } else if (atomic instanceof NullType) {\n      return Types.UnknownType.get();\n    }\n\n    throw new UnsupportedOperationException(\"Not a supported type: \" + atomic.catalogString());\n  }\n\n  // Translates Spark's edge-interpolation algorithm to Iceberg's, mirroring","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkTypeToType.java#L155-L191","documentation":"SparkTypeToType converts Spark types to Iceberg types. A Spark GeometryType with mixed SRID (coordinates referencing different spatial reference systems) cannot be represented by a single Iceberg GeometryType, which carries one CRS. Conversion throws this UnsupportedOperationException rather than silently dropping SRID information.","triggerScenarios":"Reading or writing Spark DataFrames whose schema contains a geometry column flagged as mixed-SRID while Iceberg converts the schema (e.g. SparkScan/SchemaConverter paths).","commonSituations":"Ingesting heterogeneous spatial data from multiple sources into one geometry column; lossy SRID assignment upstream in Spark; spatial ETL mixing WGS84 and projected coordinates in a single column.","solutions":["Normalize the geometry column to a single SRID before handing the schema to Iceberg (ST_Transform / reproject each geometry)","Split mixed-SRID data into separate columns per SRID","Store geometries as binary if single-SRID enforcement can't be met (with SRID managed by convention)","Reject or quarantine offending rows upstream so the column is single-SRID"],"exampleFix":"// before\ndf.select(functions.expr(\"st_setsrid(geom, 4326)\")) // mixed SRIDs remain in some rows\n// after\ndf = df.withColumn(\"geom\", functions.expr(\"st_transform(geom, 'EPSG:4326')\")); // single SRID everywhere","handlingStrategy":"validation","validationCode":"if (sparkGeomType.isMixedSrid()) {\n  throw new IllegalStateException(\"Normalize geometry SRID before Iceberg conversion\");\n}","typeGuard":"if (dt instanceof org.apache.spark.sql.types.GeometryType g && g.isMixedSrid()) {\n  return false; // not convertible until reprojected\n}","tryCatchPattern":"try {\n  icebergType = converter.convert(sparkSchema);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"mixed SRID\")) {\n    // reproject to one SRID and retry\n  }\n}","preventionTips":["Enforce single-SRID guarantees at ingestion boundaries","Reproject with ST_Transform to a canonical SRID (e.g. EPSG:4326)","Validate SRID homogeneity in ETL tests","Never mix SRIDs in one geometry column"],"tags":["spark","spatial","geometry","srid","type-conversion"],"backgroundTag":"unsupported-dtype","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"}