apache/druid · error · IllegalArgumentException

Either uri xor uriPrefix required

Error message

Either uri xor uriPrefix required

What it means

UriExtractionNamespace's constructor requires exactly one of `uri` (a single file URI) or `uriPrefix` (a URI prefix for multi-file loading) — the two are mutually exclusive and one is mandatory. When both are set, or neither is set, it throws this IAE during namespace config deserialization.

Source

Thrown at extensions-core/lookups-cached-global/src/main/java/org/apache/druid/query/lookup/namespace/UriExtractionNamespace.java:107

      @JsonProperty(value = "uriPrefix", required = false)
          URI uriPrefix,
      @JsonProperty(value = "fileRegex", required = false)
          String fileRegex,
      @JsonProperty(value = "namespaceParseSpec", required = true)
          FlatDataParser namespaceParseSpec,
      @Min(0) @JsonProperty(value = "pollPeriod", required = false) @Nullable
          Period pollPeriod,
      @Deprecated
      @JsonProperty(value = "versionRegex", required = false)
          String versionRegex,
      @JsonProperty(value = "maxHeapPercentage") @Nullable
          Long maxHeapPercentage
  )
  {
    this.uri = uri;
    this.uriPrefix = uriPrefix;
    if ((uri != null) == (uriPrefix != null)) {
      throw new IAE("Either uri xor uriPrefix required");
    }
    this.namespaceParseSpec = Preconditions.checkNotNull(namespaceParseSpec, "namespaceParseSpec");
    if (pollPeriod == null) {
      // Warning because if UriExtractionNamespace is being used for lookups, any updates to the database will not
      // be picked up after the node starts. So for use casses where nodes start at different times (like streaming
      // ingestion with peons) there can be data inconsistencies across the cluster.
      LOG.warn("No pollPeriod configured for UriExtractionNamespace - entries will be loaded only once at startup");
      this.pollPeriod = Period.ZERO;
    } else {
      this.pollPeriod = pollPeriod;
    }
    this.fileRegex = fileRegex == null ? versionRegex : fileRegex;
    if (fileRegex != null && versionRegex != null) {
      throw new IAE("Cannot specify both versionRegex and fileRegex. versionRegex is deprecated");
    }

    if (uri != null && this.fileRegex != null) {
      throw new IAE("Cannot define both uri and fileRegex");

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Remove either the `uri` or the `uriPrefix` field so exactly one remains.
  2. If the config should point at a single file, keep `uri` and delete `uriPrefix`; for a directory/prefix of files, keep `uriPrefix` and delete `uri`.
  3. Check for typo'd keys that silently leave both fields null.
  4. Validate the lookup JSON before POSTing it to the lookup coordinator.

Example fix

// before
{"type":"uri", "uri":"s3://bucket/f.csv", "uriPrefix":"s3://bucket/"}
// after
{"type":"uri", "uriPrefix":"s3://bucket/"}
Defensive patterns

Strategy: validation

Validate before calling

// java
boolean hasUri = cfg.has("uri") && !cfg.get("uri").isNull();
boolean hasPrefix = cfg.has("uriPrefix") && !cfg.get("uriPrefix").isNull();
if (hasUri == hasPrefix) throw new IllegalArgumentException("exactly one of uri/uriPrefix required");

Try / catch

// java
try { mapper.readValue(json, UriExtractionNamespace.class); }
catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Either uri xor uriPrefix")) { /* fix config */ }
}

Prevention

When it happens

Trigger: Constructing UriExtractionNamespace (or submitting lookup JSON) with both uri and uriPrefix set, or with both null/absent; Jackson binding a lookup config missing the uri field.

Common situations: Copy-pasted lookup JSON where an old `uri` field was left in place after adding `uriPrefix`; typos in field names (e.g. "url" instead of "uri") leaving both effectively null; migrated configs with leftover fields.

Related errors


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