apache/druid · error · IllegalArgumentException

Cannot specify both versionRegex and fileRegex. versionRegex

Error message

Cannot specify both versionRegex and fileRegex. versionRegex is deprecated

What it means

UriExtractionNamespace has a legacy `versionRegex` option superseded by `fileRegex`. Because versionRegex is deprecated and the semantics overlap, the constructor rejects configs that specify both at once with this IAE. Note the check compares the raw arguments, so passing identical values for both still throws.

Source

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

  {
    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");
    }

    if (this.fileRegex != null) {
      try {
        Pattern.compile(this.fileRegex);
      }
      catch (PatternSyntaxException ex) {
        throw new IAE(ex, "Could not parse `fileRegex` [%s]", this.fileRegex);
      }
    }
    this.maxHeapPercentage = maxHeapPercentage == null ? DEFAULT_MAX_HEAP_PERCENTAGE : maxHeapPercentage;
  }

  public String getFileRegex()

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Delete the deprecated `versionRegex` field and keep only `fileRegex`.
  2. Migrate the pattern from versionRegex into fileRegex if the old field held the intended pattern.
  3. Search lookup config JSON for leftover `versionRegex` keys across environments.
  4. Pin a validation step (or JSON schema) that rejects versionRegex before submitting configs.

Example fix

// before
{"uriPrefix":"s3://b/", "versionRegex":".*v[0-9]+\.csv", "fileRegex":".*v[0-9]+\.csv"}
// after
{"uriPrefix":"s3://b/", "fileRegex":".*v[0-9]+\.csv"}
Defensive patterns

Strategy: validation

Validate before calling

// bash: reject deprecated key in lookup configs
grep -l versionRegex lookups/*.json && echo "remove deprecated versionRegex" && exit 1

Try / catch

// java
try { mapper.readValue(json, UriExtractionNamespace.class); }
catch (IllegalArgumentException e) {
  if (e.getMessage().contains("versionRegex")) { /* drop versionRegex field */ }
}

Prevention

When it happens

Trigger: Constructing UriExtractionNamespace (or deserializing lookup JSON) where both `versionRegex` and `fileRegex` keys are present in the config, even with the same value.

Common situations: Configs upgraded from older Druid versions that still carry versionRegex after someone added fileRegex; template-generated lookup JSON merging old and new fields; JSON kept for backward compatibility that now conflicts.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


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