{"record":{"id":"9cfaac7f5fd5877c","repo":"apache/druid","slug":"s-column-must-have-type-s-or-no-type-found","errorCode":null,"errorMessage":"[%s] column must have type [%s] or no type. Found [%s]","messagePattern":"\\[(.+?)\\] column must have type \\[(.+?)\\] or no type\\. Found \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/catalog/model/ColumnSpec.java","lineNumber":108,"sourceCode":"  {\n    return dataType;\n  }\n\n  @JsonProperty(\"properties\")\n  @JsonInclude(Include.NON_EMPTY)\n  public Map<String, Object> properties()\n  {\n    return properties;\n  }\n\n  public void validate()\n  {\n    if (Strings.isNullOrEmpty(name)) {\n      throw new IAE(\"Column name is required\");\n    }\n    if (Columns.isTimeColumn(name)) {\n      if (dataType != null && !Columns.LONG.equalsIgnoreCase(dataType)) {\n        throw new IAE(\n            \"[%s] column must have type [%s] or no type. Found [%s]\",\n            name,\n            Columns.LONG,\n            dataType\n        );\n      }\n    }\n    // Validate type in the next PR\n  }\n\n  /**\n   * Merges an updated version of this column with an existing version.\n   * <p>\n   * The name cannot be changed (it is what links the existing column and the\n   * update). The SQL type will be that provided in the update, if non-null, else\n   * the original type. Properties are merged using standard rules: those in the\n   * update take precedence. Null values in the update remove the existing property,\n   * non-null values update the property. Any properties in the update but not in","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/catalog/model/ColumnSpec.java#L90-L126","documentation":"ColumnSpec.validate enforces that the special __time column has Druid type LONG (or no explicit type). Assigning any other dataType (e.g. string, double) to the time column is invalid because the primary time column is internally stored as a long epoch millis value.","triggerScenarios":"Calling validate() (directly or via mergeColumn/testColumnSpec) on a ColumnSpec named __time whose dataType is set to anything other than \"long\" (case-insensitive), e.g. \"string\" or \"timestamp\".","commonSituations":"Users coming from SQL intuition set the __time column type to \"timestamp\" or \"date\"; schema import from another system carries over a DATETIME/TIMESTAMP type for the time column.","solutions":["Set the __time column dataType to \"long\", or remove the dataType property entirely.","Express timestamp formatting in the ingestion timestampSpec instead of typing the column as timestamp.","Search the spec for case mismatches — \"LONG\" is accepted case-insensitively, but \"timestamp\" is not."],"exampleFix":"// before\n{\"name\": \"__time\", \"dataType\": \"timestamp\"}\n// after\n{\"name\": \"__time\", \"dataType\": \"long\"}","handlingStrategy":"validation","validationCode":"if (\"__time\".equals(spec.getName()) && spec.getDataType() != null\n    && !\"long\".equalsIgnoreCase(spec.getDataType())) {\n  throw new IllegalArgumentException(\"__time dataType must be long or omitted\");\n}","typeGuard":"boolean isValidTimeColumnType(ColumnSpec spec) {\n  return !Columns.isTimeColumn(spec.getName())\n      || spec.getDataType() == null\n      || Columns.LONG.equalsIgnoreCase(spec.getDataType());\n}","tryCatchPattern":"try { spec.validate(); } catch (IllegalArgumentException e) { // correct the __time type to long or drop dataType }","preventionTips":["Never declare __time as timestamp/string/date; use long or omit dataType.","Configure timestamp parsing via timestampSpec, not column type.","Add a spec-level lint rule that checks time-column typing."],"tags":["catalog","column","type-mismatch","validation"],"backgroundTag":"type-mismatch","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}