{"record":{"id":"765cfd5e51defefb","repo":"apache/beam","slug":"unable-to-convert-logical-type-identifier","errorCode":null,"errorMessage":"Unable to convert logical type ${identifier}","messagePattern":"Unable to convert logical type (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamCalcRel.java","lineNumber":469,"sourceCode":"        } else if (SqlTypes.DATETIME.getIdentifier().equals(identifier)) {\n          if (value instanceof Timestamp) {\n            value = SqlFunctions.toLong((Timestamp) value);\n          }\n          return LocalDateTime.of(\n              LocalDate.ofEpochDay(((Number) value).longValue() / MILLIS_PER_DAY),\n              LocalTime.ofNanoOfDay(\n                  (((Number) value).longValue() % MILLIS_PER_DAY) * NANOS_PER_MILLISECOND));\n        } else if (org.apache.beam.sdk.schemas.logicaltypes.Timestamp.IDENTIFIER.equals(\n            identifier)) {\n          if (value instanceof Timestamp) {\n            value = SqlFunctions.toLong((Timestamp) value);\n          }\n          return java.time.Instant.ofEpochMilli(((Number) value).longValue());\n        } else {\n          if (logicalType instanceof PassThroughLogicalType) {\n            return toBeamObject(value, logicalType.getBaseType(), verifyValues);\n          }\n          throw new UnsupportedOperationException(\"Unable to convert logical type \" + identifier);\n        }\n      default:\n        throw new UnsupportedOperationException(\"Unable to convert \" + fieldType.getTypeName());\n    }\n  }\n\n  private static List<Object> toBeamList(\n      List<Object> arrayValue, FieldType elementType, boolean verifyValues) {\n    return arrayValue.stream()\n        .map(e -> toBeamObject(e, elementType, verifyValues))\n        .collect(Collectors.toList());\n  }\n\n  private static Map<Object, Object> toBeamMap(\n      Map<Object, Object> mapValue,\n      FieldType keyType,\n      FieldType elementType,\n      boolean verifyValues) {","sourceCodeStart":451,"sourceCodeEnd":487,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamCalcRel.java#L451-L487","documentation":"When converting Calcite values back to Beam Row objects, toBeamObject maps each FieldType, including logical types. If a field's logical type identifier is not one of the supported ones and is not a PassThroughLogicalType, this UnsupportedOperationException is thrown. Beam SQL's Calcite bridge only understands a fixed set of logical types.","triggerScenarios":"A Beam Schema field uses a custom LogicalType (or one not supported by the SQL integration, e.g. some non-pass-through logical types like bytes-backed or enum variants) and the row passes through BeamCalcRel.toRow / toBeamObject conversion.","commonSituations":"Using a custom Schema.LogicalType defined in user code and then selecting that column in a Beam SQL query; SDK/version mismatch where a logical type added upstream isn't supported by the SQL extension yet.","solutions":["Implement PassThroughLogicalType (based on a supported base type) for your custom logical type so it passes through conversion","Convert the column to a supported base type before the SQL query (e.g. store as VARCHAR/LONG)","Map the logical type back to a primitive in the schema before running the query","Check whether your Beam version supports the logical type in the SQL extension; upgrade if a newer release added support"],"exampleFix":"// before\nFieldType.of(LogicalTypes.myCustomType());\n// after\nSchema.FieldType.of(new PassThroughLogicalType<>(...baseType VARCHAR...)); // or use VARCHAR directly","handlingStrategy":"type-guard","validationCode":"boolean sqlConvertible(Schema.FieldType t) {\n  var lt = t.getLogicalType();\n  return lt == null || lt instanceof PassThroughLogicalType || isSupportedIdentifier(lt.getIdentifier());\n}","typeGuard":"boolean isSupported(Schema.FieldType f) {\n  return f.getLogicalType() == null || f.getLogicalType() instanceof PassThroughLogicalType;\n}","tryCatchPattern":"try {\n  Row beamRow = BeamCalcRel.toRow(calciteRow, schema, verify);\n} catch (UnsupportedOperationException e) {\n  // fall back to manual conversion for the custom logical type\n}","preventionTips":["Prefer PassThroughLogicalType for custom logical types used with SQL","Restrict SQL-queried schemas to primitive and well-known logical types","Convert exotic columns to base types before the SQL transform","Pin/upgrade Beam versions deliberately when relying on new logical types"],"tags":["java","apache-beam","sql","logical-type","schema"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}