{"record":{"id":"dd87dc3a3df4ca73","repo":"apache/druid","slug":"s-must-be-a-string-or-an-array-of-strings","errorCode":null,"errorMessage":"'%s' must be a string or an array of strings","messagePattern":"'(.+?)' must be a string or an array of strings","errorType":"validation","errorClass":"IAE","httpStatus":null,"severity":"error","filePath":"extensions-core/hdfs-storage/src/main/java/org/apache/druid/inputsource/hdfs/HdfsInputSource.java","lineNumber":125,"sourceCode":"    this.inputPaths.forEach(p -> verifyProtocol(configuration, inputSourceConfig, p));\n  }\n\n  @JsonIgnore\n  @Nonnull\n  @Override\n  public Set<String> getTypes()\n  {\n    return Collections.singleton(TYPE_KEY);\n  }\n\n  public static List<String> coerceInputPathsToList(Object inputPaths, String propertyName)\n  {\n    if (inputPaths instanceof String) {\n      return Collections.singletonList((String) inputPaths);\n    } else if (inputPaths instanceof List && ((List<?>) inputPaths).stream().allMatch(x -> x instanceof String)) {\n      return ((List<?>) inputPaths).stream().map(x -> (String) x).collect(Collectors.toList());\n    } else {\n      throw new IAE(\"'%s' must be a string or an array of strings\", propertyName);\n    }\n  }\n\n  public static void verifyProtocol(Configuration conf, HdfsInputSourceConfig config, String pathString)\n  {\n    Path path = new Path(pathString);\n    try {\n      throwIfInvalidProtocol(config, path.getFileSystem(conf).getScheme());\n    }\n    catch (IOException e) {\n      throw new RuntimeException(e);\n    }\n  }\n\n  private static void throwIfInvalidProtocol(HdfsInputSourceConfig config, String scheme)\n  {\n    if (!config.getAllowedProtocols().contains(StringUtils.toLowerCase(scheme))) {\n      throw new IAE(\"Only %s protocols are allowed\", config.getAllowedProtocols());","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/hdfs-storage/src/main/java/org/apache/druid/inputsource/hdfs/HdfsInputSource.java#L107-L143","documentation":"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.","triggerScenarios":"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.","commonSituations":"Hand-edited ingestion specs; templating tools inserting non-string values; users passing a comma-joined list as an object or nesting paths incorrectly.","solutions":["Make 'paths' a JSON string or an array of strings, e.g. \"paths\": \"hdfs://nn/data\" or \"paths\": [\"hdfs://nn/a\", \"hdfs://nn/b\"].","If you have many comma-separated paths, split them into a JSON array yourself; the source does not split strings.","Validate the spec with the /druid/indexer/v1/task endpoint's validation or a JSON schema check before submitting.","Quote numeric-looking path components as strings in JSON."],"exampleFix":"// before\n\"inputSource\": {\"type\": \"hdfs\", \"paths\": 123}\n// after\n\"inputSource\": {\"type\": \"hdfs\", \"paths\": [\"hdfs://namenode:8020/druid/segments/\"]}","handlingStrategy":"validation","validationCode":"static boolean validHdfsPaths(Object paths) {\n  return paths instanceof String\n      || (paths instanceof List && ((List<?>) paths).stream().allMatch(x -> x instanceof String));\n}","typeGuard":"static List<String> asPathList(Object v) {\n  if (v instanceof String) return Collections.singletonList((String) v);\n  if (v instanceof List && ((List<?>) v).stream().allMatch(String.class::isInstance)) {\n    return ((List<?>) v).stream().map(String.class::cast).collect(Collectors.toList());\n  }\n  return null; // invalid\n}","tryCatchPattern":"try { source = mapper.readValue(spec, InputSource.class); }\ncatch (IllegalArgumentException e) {\n  log.error(\"Bad hdfs inputSource paths: %s\", e.getMessage());\n}","preventionTips":["Keep 'paths' as a JSON string or array of strings in specs.","Validate ingestion specs (schema/endpoint) before submission.","Never let templating tools emit numbers/objects into 'paths'.","Split comma-separated paths into array elements yourself."],"tags":["hdfs","input-source","validation","json"],"backgroundTag":"invalid-argument-format","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}