apache/druid · error · IllegalArgumentException

When using the %s parameter, %s must also be provided

Error message

When using the %s parameter, %s must also be provided

What it means

The S3 external table definition throws this IllegalArgumentException when the 'bucket' parameter is provided but the 'paths' parameter is absent. A bucket alone does not identify any objects; Druid needs the object keys (paths) within the bucket to build CloudObjectLocation entries. Bucket + paths are treated as a paired unit for the objects-based S3 input source.

Source

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

      );
    }
    if (!hasUris && !hasPrefixes && !hasBucket) {
      throw new IAE(
          "S3 requires one of %s, %s or %s",
          PATHS_PARAMETER,
          BUCKET_PARAMETER,
          PREFIXES_PARAMETER
      );
    }
    if (hasUris) {
      jsonMap.put(URIS_FIELD, CatalogUtils.stringListToUriList(uris));
    }
    if (hasPrefixes) {
      jsonMap.put(PREFIXES_FIELD, prefixes);
    }
    if (hasBucket) {
      if (!hasPaths) {
        throw new IAE("When using the %s parameter, %s must also be provided", BUCKET_PARAMETER, PATHS_PARAMETER);
      }
      List<CloudObjectLocation> objects = new ArrayList<>();
      for (String obj : paths) {
        objects.add(new CloudObjectLocation(bucket, obj));
      }
      jsonMap.put(OBJECTS_FIELD, objects);
    }
    if (objectGlob != null) {
      jsonMap.put(OBJECT_GLOB_FIELD, objectGlob);
    }
    applySecurityParams(jsonMap, args);
  }

  private void applySecurityParams(Map<String, Object> jsonMap, Map<String, Object> args)
  {
    final String accessKeyId = CatalogUtils.getNonBlankString(args, ACCESS_KEY_ID_PARAMETER);
    final String secretAccessKey = CatalogUtils.getNonBlankString(args, SECRET_ACCESS_KEY_PARAMETER);
    final String assumeRoleArn = CatalogUtils.getNonBlankString(args, ASSUME_ROLE_ARN_PARAMETER);

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Add the 'paths' parameter listing the object keys in the bucket.
  2. If the intent was to read everything under a prefix, drop 'bucket' and use the 'prefixes' parameter instead.
  3. If the intent was explicit files, pass full s3:// URIs via 'paths'/'uris' instead of bucket + keys.
  4. Review the table function argument map for the missing 'paths' key before invoking.

Example fix

// before
EXTERN('s3-ext' => ARRAY[], 'bucket' => 'my-bucket')
// after
EXTERN('s3-ext' => ARRAY['data/file1.json','data/file2.json'], 'bucket' => 'my-bucket')
Defensive patterns

Strategy: validation

Validate before calling

Object bucket = args.get("bucket");
List<?> paths = (List<?>) args.getOrDefault("paths", List.of());
if (bucket != null && paths.isEmpty()) {
  throw new IllegalArgumentException("'bucket' requires a non-empty 'paths' list of object keys");
}

Prevention

When it happens

Trigger: Calling the S3 external table function with a 'bucket' argument but no 'paths' argument, so hasBucket is true and hasPaths is false inside convertArgsToSourceMap.

Common situations: Assuming 'bucket' alone selects the whole bucket (that is what 'prefixes' is for); copying a config snippet that included bucket but dropping the paths line; building the argument map programmatically and leaving out the paths key.

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/7df52b214b9ebfae. Report an issue: GitHub.