{"record":{"id":"c8ab4586249723b6","repo":"apache/druid","slug":"s-property-is-required","errorCode":null,"errorMessage":"%s property is required","messagePattern":"(.+?) property is required","errorType":"validation","errorClass":"IAE","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/catalog/model/table/ResolvedExternalTable.java","lineNumber":62,"sourceCode":"  private InputSourceDefn inputSourceDefn;\n  private InputFormatDefn inputFormatDefn;\n\n  /**\n   * Construct a resolved external table by extracting the input source\n   * and input format properties, and converting each to a Java map.\n   * Validates that the input source is present: the format is optional.\n   * <p>\n   * Note: does <i>not</i> resolve the input source and input format\n   * definitions: that is done as a separate step when needed.\n   *\n   * @see {@link #resolve(TableDefnRegistry)}.\n   */\n  public ResolvedExternalTable(final ResolvedTable table)\n  {\n    this.table = table;\n    Map<String, Object> map = table.mapProperty(ExternalTableDefn.SOURCE_PROPERTY);\n    if (map == null || map.isEmpty()) {\n      throw new IAE(\"%s property is required\", ExternalTableDefn.SOURCE_PROPERTY);\n    }\n    this.inputSourceMap = new HashMap<>(map);\n    map = table.mapProperty(ExternalTableDefn.FORMAT_PROPERTY);\n    this.inputFormatMap = map == null ? null : new HashMap<>(map);\n  }\n\n  public ResolvedTable resolvedTable()\n  {\n    return table;\n  }\n\n  /**\n   * Look up the input source type and input format type to find the corresponding\n   * definitions in the table registry. Throws an exception if the types are not\n   * defined. The input source is required, the format is optional.\n   * <p>\n   * Note, for resolution to work, the name of each definition must be the same as\n   * that used as the type key in the serialized JSON.","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/catalog/model/table/ResolvedExternalTable.java#L44-L80","documentation":"Every external table resolved through the Druid catalog must carry a source property in its table spec, which holds the input-source JSON map. The ResolvedExternalTable constructor copies this map; if it is missing or empty, no input source can be built, so the constructor throws this IAE.","triggerScenarios":"Creating or registering an external table spec whose serialized properties lack the source property, or set it to an empty map/null.","commonSituations":"Hand-written table specs omitting source; API clients that only send columns; migration tooling that drops unrecognized properties; JSON key casing mismatch (Source vs source).","solutions":["Add a source property containing the input-source map (e.g. {\"type\":\"local\",\"baseDir\":\"/data\"})","Check the property key is exactly \"source\" (ExternalTableDefn.SOURCE_PROPERTY)","Recreate the table via the catalog API so required properties are populated"],"exampleFix":"// before\n{\"specType\":\"external\",\"columns\":[...]}\n// after\n{\"specType\":\"external\",\"source\":{\"type\":\"local\",\"baseDir\":\"/data\"},\"columns\":[...]}","handlingStrategy":"validation","validationCode":"// Java\nObject source = spec.get(\"source\");\nif (!(source instanceof Map) || ((Map<?,?>) source).isEmpty())\n  throw new IllegalArgumentException(\"external table spec requires non-empty 'source' property\");","typeGuard":"// Java\nstatic boolean hasSource(Map<String,Object> spec) {\n  return spec.get(\"source\") instanceof Map && !((Map<?,?>) spec.get(\"source\")).isEmpty();\n}","tryCatchPattern":"try { new ResolvedExternalTable(resolvedTable); } catch (IAE e) { if (e.getMessage().contains(\"property is required\")) { /* attach source property */ } else throw e; }","preventionTips":["Always include source in external table specs","Run spec serialization round-trips in tests to catch dropped properties","Use ExternalTableDefn.SOURCE_PROPERTY constant rather than a literal"],"tags":["druid-catalog","validation","external-table","missing-property"],"backgroundTag":"missing-required-config-field","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}