{"record":{"id":"187fb805f56b475f","repo":"apache/druid","slug":"the-table-type-is-required","errorCode":null,"errorMessage":"The table type is required.","messagePattern":"The table type is required\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/catalog/model/TableDefnRegistry.java","lineNumber":145,"sourceCode":"  {\n    this(null, null, null, jsonMapper);\n  }\n\n  public TableDefn tableDefnFor(String type)\n  {\n    return tableDefns.get(type);\n  }\n\n  public ObjectMapper jsonMapper()\n  {\n    return jsonMapper;\n  }\n\n  public ResolvedTable resolve(TableSpec spec)\n  {\n    String type = spec.type();\n    if (Strings.isNullOrEmpty(type)) {\n      throw new IAE(\"The table type is required.\");\n    }\n    TableDefn defn = tableDefns.get(type);\n    if (defn == null) {\n      throw new IAE(\"Table type [%s] is not valid.\", type);\n    }\n    return new ResolvedTable(defn, spec, jsonMapper);\n  }\n\n  /**\n   * Return input source definition for the given input source type name, or\n   * {@code null} if there is no such definition.\n   */\n  public InputSourceDefn inputSourceDefnFor(String type)\n  {\n    return inputSourceDefns.get(type);\n  }\n\n  /**","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/catalog/model/TableDefnRegistry.java#L127-L163","documentation":"TableDefnRegistry.resolve() looks up the table definition registered for a spec's type. The type field is mandatory: without it the registry cannot select a definition, so an empty/null type throws IAE before the lookup.","triggerScenarios":"Calling resolve(TableSpec) — directly or via table(), unsealed(), resolved() helpers — with a TableSpec whose type is null or empty.","commonSituations":"Deserializing a partial/incomplete table spec from JSON where the \"type\" field was omitted; building a TableSpec programmatically with a null type; legacy spec formats predating the type field.","solutions":["Populate the type field on the TableSpec (e.g. \"datasource\") before resolving","Check the source JSON includes the \"type\" property and that deserialization binds it","Validate the spec (e.g. via TableSpec.validate()) before calling resolve"],"exampleFix":"// before\nTableSpec spec = new TableSpec(null, props, columns);\nregistry.resolve(spec);\n// after\nTableSpec spec = new TableSpec(\"datasource\", props, columns);\nregistry.resolve(spec);","handlingStrategy":"validation","validationCode":"if (Strings.isNullOrEmpty(spec.type())) {\n  throw new IllegalArgumentException(\"set spec.type before resolve()\");\n}","typeGuard":"boolean isResolvable(TableSpec spec) {\n  return spec != null && spec.type() != null && !spec.type().isEmpty();\n}","tryCatchPattern":"try { return registry.resolve(spec); } catch (IllegalArgumentException e) { if (e.getMessage().equals(\"The table type is required.\")) { /* populate type or reject payload */ } else { throw e; } }","preventionTips":["Always construct TableSpec with a type","Validate specs at ingestion/deserialization boundaries","Make type a required constructor parameter in your wrappers"],"tags":["validation","registry","missing-field"],"backgroundTag":"missing-required-argument","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}