apache/druid · error · IAE

'%s' must be a string or an array of strings

Error message

'%s' must be a string or an array of strings

What it means

HdfsInputSource coerces its 'paths' property into a list of strings. If the provided value is neither a single string nor a list of strings (e.g. a number, object, or list containing non-strings), this IllegalArgumentException is thrown with the property name. It is input-validation for the HDFS input source spec.

Source

Thrown at extensions-core/hdfs-storage/src/main/java/org/apache/druid/inputsource/hdfs/HdfsInputSource.java:125

    this.inputPaths.forEach(p -> verifyProtocol(configuration, inputSourceConfig, p));
  }

  @JsonIgnore
  @Nonnull
  @Override
  public Set<String> getTypes()
  {
    return Collections.singleton(TYPE_KEY);
  }

  public static List<String> coerceInputPathsToList(Object inputPaths, String propertyName)
  {
    if (inputPaths instanceof String) {
      return Collections.singletonList((String) inputPaths);
    } else if (inputPaths instanceof List && ((List<?>) inputPaths).stream().allMatch(x -> x instanceof String)) {
      return ((List<?>) inputPaths).stream().map(x -> (String) x).collect(Collectors.toList());
    } else {
      throw new IAE("'%s' must be a string or an array of strings", propertyName);
    }
  }

  public static void verifyProtocol(Configuration conf, HdfsInputSourceConfig config, String pathString)
  {
    Path path = new Path(pathString);
    try {
      throwIfInvalidProtocol(config, path.getFileSystem(conf).getScheme());
    }
    catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  private static void throwIfInvalidProtocol(HdfsInputSourceConfig config, String scheme)
  {
    if (!config.getAllowedProtocols().contains(StringUtils.toLowerCase(scheme))) {
      throw new IAE("Only %s protocols are allowed", config.getAllowedProtocols());

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Make 'paths' a JSON string or an array of strings, e.g. "paths": "hdfs://nn/data" or "paths": ["hdfs://nn/a", "hdfs://nn/b"].
  2. If you have many comma-separated paths, split them into a JSON array yourself; the source does not split strings.
  3. Validate the spec with the /druid/indexer/v1/task endpoint's validation or a JSON schema check before submitting.
  4. Quote numeric-looking path components as strings in JSON.

Example fix

// before
"inputSource": {"type": "hdfs", "paths": 123}
// after
"inputSource": {"type": "hdfs", "paths": ["hdfs://namenode:8020/druid/segments/"]}
Defensive patterns

Strategy: validation

Validate before calling

static boolean validHdfsPaths(Object paths) {
  return paths instanceof String
      || (paths instanceof List && ((List<?>) paths).stream().allMatch(x -> x instanceof String));
}

Type guard

static List<String> asPathList(Object v) {
  if (v instanceof String) return Collections.singletonList((String) v);
  if (v instanceof List && ((List<?>) v).stream().allMatch(String.class::isInstance)) {
    return ((List<?>) v).stream().map(String.class::cast).collect(Collectors.toList());
  }
  return null; // invalid
}

Try / catch

try { source = mapper.readValue(spec, InputSource.class); }
catch (IllegalArgumentException e) {
  log.error("Bad hdfs inputSource paths: %s", e.getMessage());
}

Prevention

When it happens

Trigger: Submitting an ingestion spec whose hdfs inputSource 'paths' is a non-string (e.g. numeric path, JSON object), or an array containing nulls/numbers/objects.

Common situations: Hand-edited ingestion specs; templating tools inserting non-string values; users passing a comma-joined list as an object or nesting paths incorrectly.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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