{"record":{"id":"c78a9f095f160402","repo":"apache/druid","slug":"if-a-local-input-source-sets-property-s-it-must","errorCode":null,"errorMessage":"If a local input source sets property %s, it must also set property %s","messagePattern":"If a local input source sets property (.+?), it must also set property (.+?)","errorType":"validation","errorClass":"IAE","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/catalog/model/table/LocalInputSourceDefn.java","lineNumber":95,"sourceCode":"  }\n\n  @Override\n  public void validate(ResolvedExternalTable table)\n  {\n    final Map<String, Object> sourceMap = new HashMap<>(table.inputSourceMap);\n    final boolean hasBaseDir = sourceMap.containsKey(BASE_DIR_FIELD);\n    final boolean hasFiles = !CollectionUtils.isNullOrEmpty(CatalogUtils.safeGet(sourceMap, FILES_FIELD, List.class));\n    final boolean hasFilter = !Strings.isNullOrEmpty(CatalogUtils.getString(sourceMap, FILTER_FIELD));\n\n    if (!hasBaseDir && !hasFiles) {\n      throw new IAE(\n          \"A local input source requires one property of %s or %s\",\n          BASE_DIR_FIELD,\n          FILES_FIELD\n      );\n    }\n    if (!hasBaseDir && hasFilter) {\n      throw new IAE(\n          \"If a local input source sets property %s, it must also set property %s\",\n          FILTER_FIELD,\n          BASE_DIR_FIELD\n      );\n    }\n    if (hasBaseDir && hasFiles) {\n      throw new IAE(\n          \"A local input source accepts only one of %s or %s\",\n          BASE_DIR_FIELD,\n          FILES_FIELD\n      );\n    }\n    super.validate(table);\n  }\n\n  @Override\n  protected List<ParameterDefn> adHocTableFnParameters()\n  {","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/catalog/model/table/LocalInputSourceDefn.java#L77-L113","documentation":"A local input source's filter only applies to files discovered under baseDir, so validate rejects a config that sets filter without baseDir. Thrown as IllegalArgumentException when filter is non-empty but baseDir is absent.","triggerScenarios":"Validating a local input source where the filter field is set, the baseDir field is missing, and (per the first check) files is provided or the baseDir/files check already passed — specifically the !hasBaseDir && hasFilter case.","commonSituations":"User adds a filter pattern to a files-based local source assuming it filters that list; config template that emits filter but skips baseDir when a path variable is empty.","solutions":["Add the baseDir property alongside filter","Or remove the filter if you intend to use an explicit files list (filter does not apply to it)","Restructure the config so discovery uses baseDir + filter instead of files"],"exampleFix":"// before\n{\"type\":\"local\",\"files\":[\"/data/a.csv\"],\"filter\":\"*.csv\"}\n// after\n{\"type\":\"local\",\"baseDir\":\"/data\",\"filter\":\"*.csv\"}","handlingStrategy":"validation","validationCode":"if (src.get(\"filter\") != null && !((String) src.get(\"filter\")).isEmpty()\n    && !src.containsKey(\"baseDir\")) {\n  throw new IllegalArgumentException(\"filter requires baseDir\");\n}","typeGuard":null,"tryCatchPattern":"try { defn.validate(table); } catch (IAE e) { if (e.getMessage().contains(\"must also set property\")) { /* add baseDir or drop filter */ } else { throw e; } }","preventionTips":["Remember filter only works with baseDir-based discovery","When using an explicit files list, do not set filter","Document this constraint in config templates"],"tags":["local","input-source","validation","conflicting-options"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}