{"record":{"id":"d469dd24a75380de","repo":"apache/beam","slug":"local-timestamp-millis-can-only-be-used-with-an-underlying","errorCode":null,"errorMessage":"Local timestamp (millis) can only be used with an underlying long type","messagePattern":"Local timestamp \\(millis\\) can only be used with an underlying long type","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/schemas/utils/AvroJavaTimeConversions.java","lineNumber":51,"sourceCode":" *\n * <p>This code is copied from avro 1.10.2 TimeConversions.\n */\npublic class AvroJavaTimeConversions {\n\n  // Not defined in avro 1.8.2\n  private static final String LOCAL_TIMESTAMP_MILLIS = \"local-timestamp-millis\";\n  private static final String LOCAL_TIMESTAMP_MICROS = \"local-timestamp-micros\";\n\n  public static class LocalTimestampMillis extends LogicalType {\n    private LocalTimestampMillis() {\n      super(LOCAL_TIMESTAMP_MILLIS);\n    }\n\n    @Override\n    public void validate(Schema schema) {\n      super.validate(schema);\n      if (schema.getType() != Schema.Type.LONG) {\n        throw new IllegalArgumentException(\n            \"Local timestamp (millis) can only be used with an underlying long type\");\n      }\n    }\n  }\n\n  public static class LocalTimestampMicros extends LogicalType {\n    private LocalTimestampMicros() {\n      super(LOCAL_TIMESTAMP_MICROS);\n    }\n\n    @Override\n    public void validate(Schema schema) {\n      super.validate(schema);\n      if (schema.getType() != Schema.Type.LONG) {\n        throw new IllegalArgumentException(\n            \"Local timestamp (micros) can only be used with an underlying long type\");\n      }\n    }","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/schemas/utils/AvroJavaTimeConversions.java#L33-L69","documentation":"The LocalTimestampMillis Avro logical type is only defined over Avro 'long' underlying types. Its validate() checks the schema type and throws IllegalArgumentException if the underlying type is anything other than LONG.","triggerScenarios":"Attaching the local-timestamp-millis logical type to a schema field whose base type is int, string, etc., then validating/reading the schema through AvroJavaTimeConversions.","commonSituations":"Hand-written Avro schemas that declare timestamp-millis fields as int or string; schema registries with mistyped logical-type fields; schema evolution changing the underlying type.","solutions":["Change the field's underlying Avro type to long in the schema","Use the int-compatible logical type (time-millis/local timestamp micros only if long) that matches your base type","Regenerate the schema from the source of truth so the logical type matches long"],"exampleFix":"// before\n{\"name\": \"ts\", \"type\": \"int\", \"logicalType\": \"local-timestamp-millis\"}\n// after\n{\"name\": \"ts\", \"type\": {\"type\": \"long\", \"logicalType\": \"local-timestamp-millis\"}}","handlingStrategy":"validation","validationCode":"for (Schema.Field f : schema.getFields()) {\n  Object lt = f.schema().getLogicalType();\n  if (lt instanceof LogicalTypes.LocalTimestampMillis && f.schema().getType() != Schema.Type.LONG)\n    throw new IllegalArgumentException(\"local-timestamp-millis requires long: \" + f.name());\n}","typeGuard":"static boolean isValidLocalTimestampMillis(Schema s) {\n  return !(s.getLogicalType() instanceof LogicalTypes.LocalTimestampMillis)\n      || s.getType() == Schema.Type.LONG;\n}","tryCatchPattern":"try { conversion.validate(schema); } catch (IllegalArgumentException e) { /* fix underlying type to long */ }","preventionTips":["Validate hand-written schemas against logical-type constraints before registering them","Use Avro schema linting in CI","Never hand-edit the underlying type of logical-typed fields"],"tags":["avro","logical-type","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}