apache/druid · error · IllegalArgumentException

Path must start with '/'

Error message

Path must start with '/'

What it means

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.

Source

Thrown at server/src/main/java/org/apache/druid/rpc/RequestBuilder.java:61

public class RequestBuilder
{
  @VisibleForTesting
  static final Duration DEFAULT_TIMEOUT = Duration.standardMinutes(2);

  private final HttpMethod method;
  private final String encodedPathAndQueryString;
  private final Multimap<String, String> headers = HashMultimap.create();
  private String contentType = null;
  private byte[] content = null;
  private Duration timeout = DEFAULT_TIMEOUT;

  public RequestBuilder(final HttpMethod method, final String encodedPathAndQueryString)
  {
    this.method = Preconditions.checkNotNull(method, "method");
    this.encodedPathAndQueryString = Preconditions.checkNotNull(encodedPathAndQueryString, "encodedPathAndQueryString");

    if (!encodedPathAndQueryString.startsWith("/")) {
      throw new IAE("Path must start with '/'");
    }
  }

  public RequestBuilder header(final String header, final String value)
  {
    headers.put(header, value);
    return this;
  }

  public RequestBuilder content(final String contentType, final byte[] content)
  {
    this.contentType = Preconditions.checkNotNull(contentType, "contentType");
    this.content = Preconditions.checkNotNull(content, "content");
    return this;
  }

  public RequestBuilder objectContent(final ObjectMapper objectMapper, final String contentType, final Object content)
  {

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Prepend '/' to the path string before constructing RequestBuilder.
  2. Pass only the path (and optional query string); host/scheme come from ServiceLocation, not the builder.
  3. Validate configured endpoint paths in config classes to ensure they begin with '/'.
  4. If joining segments, normalize with a helper that guarantees a single leading slash.

Example fix

// before
new RequestBuilder(HttpMethod.GET, "druid/v2");
// after
new RequestBuilder(HttpMethod.GET, "/druid/v2");
Defensive patterns

Strategy: validation

Validate before calling

if (path == null || !path.startsWith("/")) { throw new IllegalArgumentException("path must be absolute: " + path); }
RequestBuilder b = new RequestBuilder(HttpMethod.GET, path);

Type guard

String requireAbsolutePath(String p) { return (p != null && p.startsWith("/")) ? p : "/" + p; }

Try / catch

try { return new RequestBuilder(method, encodedPath); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Path must start with")) { return new RequestBuilder(method, "/" + encodedPath); } throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/35214f116392bbb9. Report an issue: GitHub.