{"record":{"id":"651c1f6059d9f961","repo":"apache/druid","slug":"one-or-more-uris-is-required-in-parameter-s","errorCode":null,"errorMessage":"One or more URIs is required in parameter %s","messagePattern":"One or more URIs is required in parameter (.+?)","errorType":"validation","errorClass":"IAE","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/catalog/model/table/HttpInputSourceDefn.java","lineNumber":282,"sourceCode":"    } else if (!sourceMap.containsKey(URIS_FIELD)) {\n      convertUriArg(sourceMap, args);\n    }\n\n    // Get user and password from the table if defined, else from arguments.\n    if (!sourceMap.containsKey(USERNAME_FIELD) && !sourceMap.containsKey(PASSWORD_FIELD)) {\n      convertUserPasswordArgs(sourceMap, args);\n    }\n    if (!sourceMap.containsKey(HEADERS_FIELD)) {\n      convertHeaderArg(sourceMap, args);\n    }\n    return convertPartialFormattedTable(table, args, columns, sourceMap);\n  }\n\n  private void convertUriTemplateArgs(Map<String, Object> jsonMap, String uriTemplate, Map<String, Object> args)\n  {\n    List<String> uriStrings = CatalogUtils.getStringArray(args, URIS_PARAMETER);\n    if (CollectionUtils.isNullOrEmpty(uriStrings)) {\n      throw new IAE(\"One or more URIs is required in parameter %s\", URIS_PARAMETER);\n    }\n    final Matcher m = templateMatcher(uriTemplate);\n    final List<String> uris = uriStrings.stream()\n        .map(uri -> m.replaceFirst(uri))\n        .collect(Collectors.toList());\n    jsonMap.put(URIS_FIELD, CatalogUtils.stringListToUriList(uris));\n  }\n\n  /**\n   * URIs in SQL is in the form of a string that contains a comma-delimited\n   * set of URIs. Done since SQL doesn't support array scalars.\n   */\n  private void convertUriArg(Map<String, Object> jsonMap, Map<String, Object> args)\n  {\n    List<String> uris = CatalogUtils.getStringArray(args, URIS_PARAMETER);\n    if (uris != null) {\n      jsonMap.put(URIS_FIELD, CatalogUtils.stringListToUriList(uris));\n    }","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/catalog/model/table/HttpInputSourceDefn.java#L264-L300","documentation":"Thrown by HttpInputSourceDefn.convertUriTemplateArgs when converting a completed template-based HTTP table: the 'uris' argument list (the concrete values substituted into the template's '{}' placeholder) is missing or empty. The template alone is not enough; the actual URI fragments must be supplied.","triggerScenarios":"convertCompletedTable on a template-based table whose args map has no URIS_PARAMETER entries (null or empty string array).","commonSituations":"Finalizing a table from partial form data where the user never entered URI values; an API caller that set uriTemplate but not the uris argument; whitespace-only lists passing isNullOrEmpty checks incorrectly upstream.","solutions":["Provide the 'uris' argument with at least one value, e.g. {\"uris\": [\"file1.json\"]}","Check the form/tool that collects URI fragments is populating the args map","Ensure values are the fragments to substitute into '{}', full URLs not needed"],"exampleFix":"// before\nargs = {\"uriTemplate\": \"https://h/{}.json\"} // uris missing\n// after\nargs = {\"uriTemplate\": \"https://h/{}.json\", \"uris\": [\"2024-01\"]}","handlingStrategy":"validation","validationCode":"if (uriTemplate != null && (args.get(\"uris\") == null || ((java.util.List<String>) args.get(\"uris\")).isEmpty())) { throw new IAE(\"uris required\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Collect URI fragments in forms before finalizing","Keep template and uris together in generators","Test convertCompletedTable on sample data"],"tags":["catalog","http","missing-parameter"],"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-14T11:17:12.474Z"}