{"record":{"id":"9efe13aa1c658666","repo":"apache/druid","slug":"bad-state","errorCode":"BAD_STATE","errorMessage":"Table %s has an invalid type [%s]","messagePattern":"Table (.+?) has an invalid type \\[(.+?)\\]","errorType":"error_code","errorClass":"CatalogException","httpStatus":500,"severity":"error","filePath":"extensions-core/druid-catalog/src/main/java/org/apache/druid/catalog/http/TableEditor.java","lineNumber":283,"sourceCode":"    final TableDefn defn = resolveDefn(existingSpec.type());\n    final Map<String, Object> revised = defn.mergeProperties(\n        existingSpec.properties(),\n        updates\n    );\n    try {\n      defn.validate(revised, catalog.jsonMapper());\n    }\n    catch (IAE e) {\n      throw CatalogException.badRequest(e.getMessage());\n    }\n    return existingSpec.withProperties(revised);\n  }\n\n  private TableDefn resolveDefn(String tableType) throws CatalogException\n  {\n    TableDefn defn = catalog.tableRegistry().tableDefnFor(tableType);\n    if (defn == null) {\n      throw new CatalogException(\n          CatalogException.BAD_STATE,\n          Response.Status.INTERNAL_SERVER_ERROR,\n          \"Table %s has an invalid type [%s]\",\n          id.sqlName(),\n          tableType\n      );\n    }\n    return defn;\n  }\n\n  private long updateColumns(final List<ColumnSpec> updates) throws CatalogException\n  {\n    if (CollectionUtils.isNullOrEmpty(updates)) {\n      return 0;\n    }\n    return catalog.tables().updateColumns(\n        id,\n        table -> applyUpdateColumns(table, updates)","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/druid-catalog/src/main/java/org/apache/druid/catalog/http/TableEditor.java#L265-L301","documentation":"TableEditor.resolveDefn() looks up the TableDefn class registered for a table's type string. A null result means the stored table definition references a type unknown to the current catalog registry — an internal inconsistency, so it throws a CatalogException with BAD_STATE code and HTTP 500. This should be impossible for valid data and usually indicates corrupt metadata or a missing type registration (e.g. after an extension providing the type was removed).","triggerScenarios":"Loading/editing a table (via defn()) whose stored 'type' field has no matching TableDefn in the registry, e.g. type added by an extension that is no longer loaded, or a hand-edited/damaged table definition in metadata storage.","commonSituations":"Upgrading or downgrading Druid where the catalog no longer registers a table type; uninstalling an extension that defined custom table types while catalog metadata still references them; manual edits to metadata-store entries introducing an invalid type string.","solutions":["Check the type value in the error against tables registered in the running Druid version (registry/tableDefnFor) — fix the table definition's type to a valid registered type.","Re-enable/install the extension or module that registers the missing TableDefn type and restart Druid.","If the table definition is corrupt or obsolete, delete or repair it in the metadata store through a valid catalog resource call or migration script."],"exampleFix":"// before\nPATCH .../catalog/tables/druid.foo  {\"type\":\"streamV9\"} // unregistered type\n\n// after\nPATCH .../catalog/tables/druid.foo  {\"type\":\"datasource\"}","handlingStrategy":"validation","validationCode":"const table = await fetch(`/druid-ext/v1/catalog/tables/${tableId}`).then(r => r.json());\nconst KNOWN_TYPES = new Set(['datasource']);\nfunction hasValidType(t) { return KNOWN_TYPES.has(t.type); }\nif (!hasValidType(table)) throw new Error('unknown table type: ' + table.type);","typeGuard":null,"tryCatchPattern":"try {\n  const defn = editor.defn();\n} catch (CatalogException e) {\n  if (CatalogException.BAD_STATE.equals(e.getCode())) {\n    // reload table, verify extension providing the type is loaded, or repair/delete the table\n  }\n}","preventionTips":["Ensure all extensions that register TableDefn types are loaded on every catalog-serving node.","Never hand-edit table definitions in the metadata store; use catalog APIs.","During upgrades, verify stored table types exist in the new version before loading them in editors."],"tags":["catalog","bad-state","table-type"],"backgroundTag":"internal-invariant-violation","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"}