{"record":{"id":"0e02cbae242ffe3c","repo":"apache/druid","slug":"mismatch-in-expected-d-vs-actual-s-field-count","errorCode":null,"errorMessage":"Mismatch in expected[%d] vs actual[%s] field count","messagePattern":"Mismatch in expected\\[(.+?)\\] vs actual\\[(.+?)\\] field count","errorType":"exception","errorClass":"IllegalStateException (ISE)","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/scan/ScanQueryQueryToolChest.java","lineNumber":299,"sourceCode":"\n          for (int i = 0; i < fields.size(); i++) {\n            rowArray[i] = row.get(fields.get(i));\n          }\n\n          return rowArray;\n        };\n        break;\n      case RESULT_FORMAT_COMPACTED_LIST:\n        mapper = (List<Object> row) -> {\n          if (row.size() == fields.size()) {\n            return row.toArray();\n          } else if (fields.isEmpty()) {\n            return new Object[0];\n          } else {\n            // Uh oh... mismatch in expected and actual field count. I don't think this should happen, so let's\n            // throw an exception. If this really does happen, and there's a good reason for it, then we should remap\n            // the result row here.\n            throw new ISE(\"Mismatch in expected[%d] vs actual[%s] field count\", fields.size(), row.size());\n          }\n        };\n        break;\n      default:\n        throw new UOE(\"Unsupported resultFormat for array-based results: %s\", resultFormat);\n    }\n    return mapper;\n  }\n}\n","sourceCodeStart":281,"sourceCodeEnd":309,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/scan/ScanQueryQueryToolChest.java#L281-L309","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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).","Re-run the scan against a consistent set of segments, or compact/reindex segments so all share the same schema.","If the mismatch is legitimate, remap the result row in a custom resultFormat mapper rather than relying on the default one.","Check for custom extensions or intermediary operators that alter row arity between the query and the format mapper."],"exampleFix":"// before: query built with stale columns\nScanQuery q = new ScanQuery(..., Arrays.asList(\"col1\",\"col2\"), ...);\n// after: use null columns to derive fields from segment schema, or fix the list\nScanQuery q = new ScanQuery(..., null /* all columns */, ...);","handlingStrategy":"validation","validationCode":"if (row.size() != fields.size()) {\n  throw new IllegalArgumentException(\"Scan row field count \" + row.size() + \" != expected \" + fields.size());\n}","typeGuard":"boolean fieldsMatch(ScanResultValue sv, List<String> fields) { return sv.getEvents() instanceof List && fields != null; }","tryCatchPattern":"try {\n  Sequence<Object[]> rows = mapper.apply(resultValue);\n} catch (IllegalStateException e) {\n  if (e.getMessage().startsWith(\"Mismatch in expected\")) { /* re-query with consistent columns */ }\n  else throw e;\n}","preventionTips":["Keep the query columns list null (all columns) or keep it in sync with segment schema.","Compact segments after schema changes so all segments share columns.","Never mutate ScanResultValue.events without updating columns."],"tags":["druid","scan-query","schema-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}