apache/druid · error · IAE

property is required

Error message

%s property is required

What it means

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.

Solutions

  1. Add a source property containing the input-source map (e.g. {"type":"local","baseDir":"/data"})
  2. Check the property key is exactly "source" (ExternalTableDefn.SOURCE_PROPERTY)
  3. Recreate the table via the catalog API so required properties are populated

Example fix

// before
{"specType":"external","columns":[...]}
// after
{"specType":"external","source":{"type":"local","baseDir":"/data"},"columns":[...]}
Defensive patterns

Strategy: validation

Validate before calling

// Java
Object source = spec.get("source");
if (!(source instanceof Map) || ((Map<?,?>) source).isEmpty())
  throw new IllegalArgumentException("external table spec requires non-empty 'source' property");

Type guard

// Java
static boolean hasSource(Map<String,Object> spec) {
  return spec.get("source") instanceof Map && !((Map<?,?>) spec.get("source")).isEmpty();
}

Try / catch

try { new ResolvedExternalTable(resolvedTable); } catch (IAE e) { if (e.getMessage().contains("property is required")) { /* attach source property */ } else throw e; }

Prevention

When it happens

Trigger: Creating or registering an external table spec whose serialized properties lack the source property, or set it to an empty map/null.

Common situations: 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).

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/c8ab4586249723b6. Report an issue: GitHub.

Appendix: source

Thrown at server/src/main/java/org/apache/druid/catalog/model/table/ResolvedExternalTable.java:62

  private InputSourceDefn inputSourceDefn;
  private InputFormatDefn inputFormatDefn;

  /**
   * Construct a resolved external table by extracting the input source
   * and input format properties, and converting each to a Java map.
   * Validates that the input source is present: the format is optional.
   * <p>
   * Note: does <i>not</i> resolve the input source and input format
   * definitions: that is done as a separate step when needed.
   *
   * @see {@link #resolve(TableDefnRegistry)}.
   */
  public ResolvedExternalTable(final ResolvedTable table)
  {
    this.table = table;
    Map<String, Object> map = table.mapProperty(ExternalTableDefn.SOURCE_PROPERTY);
    if (map == null || map.isEmpty()) {
      throw new IAE("%s property is required", ExternalTableDefn.SOURCE_PROPERTY);
    }
    this.inputSourceMap = new HashMap<>(map);
    map = table.mapProperty(ExternalTableDefn.FORMAT_PROPERTY);
    this.inputFormatMap = map == null ? null : new HashMap<>(map);
  }

  public ResolvedTable resolvedTable()
  {
    return table;
  }

  /**
   * Look up the input source type and input format type to find the corresponding
   * definitions in the table registry. Throws an exception if the types are not
   * defined. The input source is required, the format is optional.
   * <p>
   * Note, for resolution to work, the name of each definition must be the same as
   * that used as the type key in the serialized JSON.

View on GitHub (pinned to 9b90983fd2)