{"record":{"id":"35214f116392bbb9","repo":"apache/druid","slug":"path-must-start-with-35214f","errorCode":null,"errorMessage":"Path must start with '/'","messagePattern":"Path must start with '/'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/rpc/RequestBuilder.java","lineNumber":61,"sourceCode":"public class RequestBuilder\n{\n  @VisibleForTesting\n  static final Duration DEFAULT_TIMEOUT = Duration.standardMinutes(2);\n\n  private final HttpMethod method;\n  private final String encodedPathAndQueryString;\n  private final Multimap<String, String> headers = HashMultimap.create();\n  private String contentType = null;\n  private byte[] content = null;\n  private Duration timeout = DEFAULT_TIMEOUT;\n\n  public RequestBuilder(final HttpMethod method, final String encodedPathAndQueryString)\n  {\n    this.method = Preconditions.checkNotNull(method, \"method\");\n    this.encodedPathAndQueryString = Preconditions.checkNotNull(encodedPathAndQueryString, \"encodedPathAndQueryString\");\n\n    if (!encodedPathAndQueryString.startsWith(\"/\")) {\n      throw new IAE(\"Path must start with '/'\");\n    }\n  }\n\n  public RequestBuilder header(final String header, final String value)\n  {\n    headers.put(header, value);\n    return this;\n  }\n\n  public RequestBuilder content(final String contentType, final byte[] content)\n  {\n    this.contentType = Preconditions.checkNotNull(contentType, \"contentType\");\n    this.content = Preconditions.checkNotNull(content, \"content\");\n    return this;\n  }\n\n  public RequestBuilder objectContent(final ObjectMapper objectMapper, final String contentType, final Object content)\n  {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/rpc/RequestBuilder.java#L43-L79","documentation":"RequestBuilder's constructor validates that the encodedPathAndQueryString argument is an absolute path starting with '/'. Passing a relative path or full URL throws an IllegalArgumentException immediately.","triggerScenarios":"Constructing RequestBuilder with a path like \"status\" or \"http://host/status\" instead of \"/status\"; string-concatenating a base URL into the path argument; variables holding empty or malformed path strings.","commonSituations":"Devs used to full-URL HTTP clients passing absolute URLs into RequestBuilder; config-driven paths missing the leading slash; joining path segments incorrectly in custom ServiceClient implementations.","solutions":["Prepend '/' to the path string before constructing RequestBuilder.","Pass only the path (and optional query string); host/scheme come from ServiceLocation, not the builder.","Validate configured endpoint paths in config classes to ensure they begin with '/'.","If joining segments, normalize with a helper that guarantees a single leading slash."],"exampleFix":"// before\nnew RequestBuilder(HttpMethod.GET, \"druid/v2\");\n// after\nnew RequestBuilder(HttpMethod.GET, \"/druid/v2\");","handlingStrategy":"validation","validationCode":"if (path == null || !path.startsWith(\"/\")) { throw new IllegalArgumentException(\"path must be absolute: \" + path); }\nRequestBuilder b = new RequestBuilder(HttpMethod.GET, path);","typeGuard":"String requireAbsolutePath(String p) { return (p != null && p.startsWith(\"/\")) ? p : \"/\" + p; }","tryCatchPattern":"try { return new RequestBuilder(method, encodedPath); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"Path must start with\")) { return new RequestBuilder(method, \"/\" + encodedPath); } throw e; }","preventionTips":["Always pass path-only strings beginning with '/'","Never concatenate base URLs into the path argument","Validate configured endpoint paths at config load","Normalize joined path segments to a single leading slash"],"tags":["http","url","validation","rpc"],"backgroundTag":"invalid-url-format","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"}