apache/druid · error · IllegalStateException (ISE)

Mismatch in expected[%d] vs actual[%s] field count

Error message

Mismatch in expected[%d] vs actual[%s] field count

What it means

ScanQuery's result format mapper converts each result row into an array of values aligned with the query's requested field list. If a row's value count does not match the expected number of fields, Druid throws this IllegalStateException because the row cannot be safely remapped positionally.

Source

Thrown at processing/src/main/java/org/apache/druid/query/scan/ScanQueryQueryToolChest.java:299

          for (int i = 0; i < fields.size(); i++) {
            rowArray[i] = row.get(fields.get(i));
          }

          return rowArray;
        };
        break;
      case RESULT_FORMAT_COMPACTED_LIST:
        mapper = (List<Object> row) -> {
          if (row.size() == fields.size()) {
            return row.toArray();
          } else if (fields.isEmpty()) {
            return new Object[0];
          } else {
            // Uh oh... mismatch in expected and actual field count. I don't think this should happen, so let's
            // throw an exception. If this really does happen, and there's a good reason for it, then we should remap
            // the result row here.
            throw new ISE("Mismatch in expected[%d] vs actual[%s] field count", fields.size(), row.size());
          }
        };
        break;
      default:
        throw new UOE("Unsupported resultFormat for array-based results: %s", resultFormat);
    }
    return mapper;
  }
}

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure the ScanQuery's columns list matches the actual columns of every segment being scanned (or query with an empty/consistent column list so results are self-describing).
  2. Re-run the scan against a consistent set of segments, or compact/reindex segments so all share the same schema.
  3. If the mismatch is legitimate, remap the result row in a custom resultFormat mapper rather than relying on the default one.
  4. Check for custom extensions or intermediary operators that alter row arity between the query and the format mapper.

Example fix

// before: query built with stale columns
ScanQuery q = new ScanQuery(..., Arrays.asList("col1","col2"), ...);
// after: use null columns to derive fields from segment schema, or fix the list
ScanQuery q = new ScanQuery(..., null /* all columns */, ...);
Defensive patterns

Strategy: validation

Validate before calling

if (row.size() != fields.size()) {
  throw new IllegalArgumentException("Scan row field count " + row.size() + " != expected " + fields.size());
}

Type guard

boolean fieldsMatch(ScanResultValue sv, List<String> fields) { return sv.getEvents() instanceof List && fields != null; }

Try / catch

try {
  Sequence<Object[]> rows = mapper.apply(resultValue);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Mismatch in expected")) { /* re-query with consistent columns */ }
  else throw e;
}

Prevention

When it happens

Trigger: Calling resultsAsFrames or the row mapper (e.g. via Sequences.map on scan results) when a ScanResultValue row contains a different number of values than the fields listed in the ScanQuery's columns list; typically after schema changed mid-scan or custom code built a ScanResultValue with mismatched columns/events.

Common situations: Segment schema drift (columns added/removed between segments scanned in one query), manually constructing ScanResultValues in tests/tools, or custom QueryToolChest extensions feeding rows with stale column lists.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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