{"record":{"id":"005d29088ca31b9e","repo":"apache/druid","slug":"a-local-input-source-requires-one-parameter-of-s","errorCode":null,"errorMessage":"A local input source requires one parameter of %s or %s","messagePattern":"A local input source requires one parameter of (.+?) or (.+?)","errorType":"validation","errorClass":"IAE","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/catalog/model/table/LocalInputSourceDefn.java","lineNumber":133,"sourceCode":"        new Parameter(BASE_DIR_PARAMETER, ParameterType.VARCHAR, true),\n        FILTER_PARAM_DEFN,\n        FILES_PARAM_DEFN\n    );\n  }\n\n  @Override\n  protected void convertArgsToSourceMap(Map<String, Object> jsonMap, Map<String, Object> args)\n  {\n    jsonMap.put(InputSource.TYPE_PROPERTY, LocalInputSource.TYPE_KEY);\n\n    final String baseDirParam = CatalogUtils.getString(args, BASE_DIR_PARAMETER);\n    final List<String> filesParam = CatalogUtils.getStringArray(args, FILES_PARAMETER);\n    final String filterParam = CatalogUtils.getString(args, FILTER_PARAMETER);\n    final boolean hasBaseDir = !Strings.isNullOrEmpty(baseDirParam);\n    final boolean hasFiles = !CollectionUtils.isNullOrEmpty(filesParam);\n    final boolean hasFilter = !Strings.isNullOrEmpty(filterParam);\n    if (!hasBaseDir && !hasFiles) {\n      throw new IAE(\n          \"A local input source requires one parameter of %s or %s\",\n          BASE_DIR_PARAMETER,\n          FILES_PARAMETER\n      );\n    }\n    if (hasBaseDir && hasFiles) {\n      if (hasFilter) {\n        throw new IAE(\n            \"A local input source can set parameter %s or %s, but not both.\",\n            FILES_PARAMETER,\n            FILTER_PARAMETER\n        );\n      }\n      // Special workaround: if the user provides a base dir, and files, convert\n      // the files to be absolute paths relative to the base dir. Then, remove\n      // the baseDir, since the Druid input source does not allow both a baseDir\n      // and a list of files.\n      jsonMap.put(FILES_FIELD, absolutePath(baseDirParam, filesParam));","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/catalog/model/table/LocalInputSourceDefn.java#L115-L151","documentation":"The Druid catalog's local input source table function requires either a baseDir parameter or a files parameter when converting table-function arguments into an input-source JSON map. If both are absent there is no way to identify which local files to read, so convertArgsToSourceMap throws this IAE. It is a user-facing validation error for incomplete table function calls.","triggerScenarios":"Calling the local-input-source table function (e.g. in SQL TABLE(...) syntax) with neither baseDir nor files supplied, or passing null/empty-string baseDir and an empty or missing files array.","commonSituations":"Writing TABLE('local', ...) in SQL and forgetting required arguments; building table-function args programmatically and leaving files empty; copy-pasting a call and deleting the files argument.","solutions":["Add a files parameter listing the local files to read, e.g. TABLE('local', FILES => ARRAY['/path/a.json'])","Add a baseDir parameter (optionally with filter) instead of files","Verify argument names match baseDir/files/filter exactly — misspelled names are silently ignored"],"exampleFix":"// before\nSELECT * FROM TABLE(EXTERN('local'))\n// after\nSELECT * FROM TABLE(EXTERN('local', FILES => ARRAY['/data/events.json']))","handlingStrategy":"validation","validationCode":"// Java\nboolean hasBaseDir = args.get(\"baseDir\") != null && !((String) args.get(\"baseDir\")).isEmpty();\nObject files = args.get(\"files\");\nboolean hasFiles = files instanceof List && !((List<?>) files).isEmpty();\nif (!hasBaseDir && !hasFiles) throw new IllegalArgumentException(\"Provide baseDir or files\");","typeGuard":"// Java\nstatic boolean hasNonEmpty(Object v) { return v instanceof String && !((String) v).isEmpty(); }\nstatic boolean hasItems(Object v) { return v instanceof List && !((List<?>) v).isEmpty(); }","tryCatchPattern":"try { tableFn.convert(args); } catch (IAE e) { if (e.getMessage().contains(\"requires one parameter\")) { /* prompt user for baseDir/files */ } else throw e; }","preventionTips":["Always pass either files or baseDir to the local input source table function","Validate argument maps before invoking the table function","Remember arguments are matched by exact name: baseDir, files, filter"],"tags":["druid-catalog","validation","table-function","local-input-source"],"backgroundTag":"missing-required-argument","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}