apache/druid · error · IllegalArgumentException

S3 external table defines the %s property. The table functio

Error message

S3 external table defines the %s property. The table function must provide the %s parameter

What it means

This IllegalArgumentException is thrown in convertCompletedTable when the catalog S3 external table definition includes a 'bucket' property, which means the user is expected to supply the objects, but the table function call did not provide the 'paths' parameter (or provided an empty list). The catalog property shifts responsibility for object selection from the catalog definition to the caller, and the caller did not fulfill it.

Source

Thrown at extensions-core/s3-extensions/src/main/java/org/apache/druid/catalog/model/table/S3InputSourceDefn.java:318

    return new PartialTableFunction(table, params);
  }

  @Override
  protected ExternalTableSpec convertCompletedTable(
      final ResolvedExternalTable table,
      final Map<String, Object> args,
      final List<ColumnSpec> columns
  )
  {
    final Map<String, Object> sourceMap = new HashMap<>(table.inputSourceMap);

    // If a bucket parameter is provided, user provides the objects. Else, use the
    // catalog input source definition.
    final String bucket = table.resolvedTable().stringProperty(BUCKET_PROPERTY);
    if (bucket != null) {
      List<String> paths = CatalogUtils.getStringArray(args, PATHS_PARAMETER);
      if (CollectionUtils.isNullOrEmpty(paths)) {
        throw new IAE(
            "S3 external table defines the %s property. The table function must provide the %s parameter",
            BUCKET_PROPERTY,
            PATHS_PARAMETER
        );
      }
      List<CloudObjectLocation> objects = new ArrayList<>();
      for (String obj : paths) {
        objects.add(new CloudObjectLocation(bucket, obj));
      }
      sourceMap.put(OBJECTS_FIELD, objects);
    }

    applySecurityParams(sourceMap, args);
    return convertPartialFormattedTable(table, args, columns, sourceMap);
  }
}

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Supply a non-empty 'paths' parameter (array of object keys) in the table function call.
  2. Check the catalog table definition: if bucketProperty is set, paths are mandatory at call time.
  3. Ensure 'paths' is passed as a string array, not a scalar or JSON string.
  4. Alternatively, redefine the catalog table with URIs/prefixes in the input source instead of bucket + per-call paths.

Example fix

// before
SELECT * FROM TABLE(EXTERN('my_s3_table'))
// after
SELECT * FROM TABLE(EXTERN('my_s3_table', 'paths' => ARRAY['data/2024/part-1.json','data/2024/part-2.json']))
Defensive patterns

Strategy: validation

Validate before calling

if (catalogTable.hasProperty("bucket")) {
  List<String> paths = args.get("paths");
  if (paths == null || paths.isEmpty()) {
    throw new IllegalArgumentException("Catalog table defines 'bucket'; pass a non-empty 'paths' array to the table function");
  }
}

Prevention

When it happens

Trigger: Querying a catalog-defined S3 external table whose resolved table has a bucketProperty set, via a table function call whose args contain no non-empty value for the 'paths' parameter (CatalogUtils.getStringArray returns null or empty).

Common situations: Calling a catalog S3 table with SELECT * without the table function arguments; passing paths as the wrong type (single string vs array) so getStringArray sees it as empty; the catalog admin added the bucket property, changing the required call signature.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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