apache/druid · error · IllegalStateException

bitmapEncoding[ ] does not match indexSpec.bitmap[ ]

Error message

bitmapEncoding[%s] does not match indexSpec.bitmap[%s]

What it means

NestedCommonFormatColumnFormatSpec.getEffectiveFormatSpec() builds the effective column format by combining the persisted columnFormatSpec with the segment indexSpec. If the builder's bitmapEncoding (which only the internal builder may set, never the JSON spec) disagrees with indexSpec.getBitmapSerdeFactory(), an internal invariant is violated and it throws an ISE.

Solutions

  1. Regenerate the segment: remove the offending column's formatSpec JSON so bitmapEncoding is derived solely from indexSpec.
  2. Set indexSpec.bitmap in the ingestion spec to the same bitmap serde as any explicitly constructed builder.
  3. Re-ingest the data to produce fresh, consistent segment metadata.
  4. Check for external tooling writing segment descriptors directly and stop it from setting bitmapEncoding.

Example fix

// before: conflicting config in ingestion spec
// "indexSpec": {"bitmap": {"type": "roaring"}}, column format built with CONCISE bitmapEncoding
// after: let indexSpec drive it
// NestedCommonFormatColumnFormatSpec.builder() // do NOT call setBitmapEncoding
//   .setBitmapEncoding(indexSpec.getBitmapSerdeFactory()).build()
Defensive patterns

Strategy: validation

Validate before calling

// ensure any explicitly constructed format spec matches indexSpec before use
if (formatSpec != null && formatSpec.getBitmapEncoding() != null &&
    !formatSpec.getBitmapEncoding().equals(indexSpec.getBitmapSerdeFactory())) {
  throw new IllegalArgumentException("bitmapEncoding must match indexSpec.bitmap");
}

Try / catch

try {
  spec = NestedCommonFormatColumnFormatSpec.getEffectiveFormatSpec(indexSpec, columnFormatSpec, ...);
} catch (IllegalStateException e) {
  if (e.getMessage().contains("bitmapEncoding")) {
    log.error(e, "Column format bitmapEncoding conflicts with indexSpec");
  } else throw e;
}

Prevention

When it happens

Trigger: Deserializing a nested column format spec whose JSON contains a bitmapEncoding that conflicts with the segment metadata's indexSpec bitmap serde factory; corrupted or hand-edited segment metadata.

Common situations: Hand-modified or programmatically written segment metadata where bitmapEncoding was set via JSON against the documented restriction; mismatch between writer's indexSpec and column metadata after tampering or partial writes.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/segment/nested/NestedCommonFormatColumnFormatSpec.java:78

  /**
   * Create a {@link NestedCommonFormatColumnFormatSpec} with all fields fully populated. Values are populated in the following order:
   * <ul>
   *   <li> value in the given column format spec, if non-null </li>
   *   <li> value in {@link IndexSpec#getAutoColumnFormatSpec()}, if non-null </li>
   *   <li> fall back to equivalent fields on {@link IndexSpec} itself if applicable </li>
   *   <li> hard coded defaults in {@link #DEFAULT}</li>
   * </ul>
   */
  public static NestedCommonFormatColumnFormatSpec getEffectiveFormatSpec(
      @Nullable NestedCommonFormatColumnFormatSpec columnFormatSpec,
      IndexSpec indexSpec
  )
  {
    final Builder builder = columnFormatSpec == null ? builder() : builder(columnFormatSpec);

    // this is a defensive check, the json spec of the column can't set this, only the builder can
    if (builder.bitmapEncoding != null && !builder.bitmapEncoding.equals(indexSpec.getBitmapSerdeFactory())) {
      throw new ISE(
          "bitmapEncoding[%s] does not match indexSpec.bitmap[%s]",
          builder.bitmapEncoding,
          indexSpec.getBitmapSerdeFactory()
      );
    }
    builder.setBitmapEncoding(indexSpec.getBitmapSerdeFactory());

    final NestedCommonFormatColumnFormatSpec defaultSpec;
    if (indexSpec.getAutoColumnFormatSpec() != null) {
      defaultSpec = indexSpec.getAutoColumnFormatSpec();
    } else {
      defaultSpec = DEFAULT;
    }

    if (builder.longFieldBitmapIndexType == null) {
      if (defaultSpec.getLongFieldBitmapIndexType() != null) {
        builder.setLongFieldBitmapIndexType(defaultSpec.getLongFieldBitmapIndexType());
      } else {

View on GitHub (pinned to 9b90983fd2)