{"record":{"id":"d626f1c46b278fb7","repo":"apache/druid","slug":"number-of-partitions-not-known-for-s-with-maxpa","errorCode":null,"errorMessage":"Number of partitions not known for [%s] with maxPartitions[%d].","messagePattern":"Number of partitions not known for \\[(.+?)\\] with maxPartitions\\[(.+?)\\]\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"multi-stage-query/src/main/java/org/apache/druid/msq/kernel/GlobalSortMaxCountShuffleSpec.java","lineNumber":146,"sourceCode":"        return Either.error((long) generatedPartitions.size());\n      }\n    }\n  }\n\n  @Override\n  @JsonProperty\n  public ClusterBy clusterBy()\n  {\n    return clusterBy;\n  }\n\n  @Override\n  public int partitionCount()\n  {\n    if (maxPartitions == 1) {\n      return 1;\n    } else {\n      throw new ISE(\"Number of partitions not known for [%s] with maxPartitions[%d].\", kind(), maxPartitions);\n    }\n  }\n\n  @JsonProperty(\"partitions\")\n  public int getMaxPartitions()\n  {\n    return maxPartitions;\n  }\n\n  @Override\n  @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = LimitHintJsonIncludeFilter.class)\n  @JsonProperty\n  public long limitHint()\n  {\n    return limitHint;\n  }\n\n  @Override","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/multi-stage-query/src/main/java/org/apache/druid/msq/kernel/GlobalSortMaxCountShuffleSpec.java#L128-L164","documentation":"GlobalSortMaxCountShuffleSpec.partitionCount() can only return a definitive count when maxPartitions == 1. For any other maxPartitions the actual number of partitions is determined only after stage execution, so calling partitionCount() throws ISE. Callers must use generatePartitionsForGlobalSort or maxPartitions instead.","triggerScenarios":"Calling partitionCount() on a GlobalSortMaxCountShuffleSpec whose maxPartitions is greater than 1 (e.g. code that assumes partitioning is known up front, such as broadcast-side sizing or partition-count reporting).","commonSituations":"Framework code querying a shuffle spec's partition count before the cluster-by statistics collector has run; distributed queries where maxPartitions was configured > 1.","solutions":["If a single partition is intended, configure maxPartitions = 1 so partitionCount() succeeds","Use getMaxPartitions() (the @JsonProperty accessor) instead of partitionCount() to read the configured cap","Treat partitionCount() as unavailable for this spec and handle it via the worker-stage logic that computes partitions dynamically"],"exampleFix":"// before\nint count = shuffleSpec.partitionCount();\n// after\nint count = shuffleSpec.getMaxPartitions(); // or handle ISE when maxPartitions != 1","handlingStrategy":"type-guard","validationCode":"if (shuffleSpec instanceof GlobalSortMaxCountShuffleSpec\n    && ((GlobalSortMaxCountShuffleSpec) shuffleSpec).getMaxPartitions() != 1) {\n  // partitionCount() will throw; use getMaxPartitions() instead\n}","typeGuard":"static boolean partitionCountKnown(ShuffleSpec spec) {\n  if (spec instanceof GlobalSortMaxCountShuffleSpec) {\n    return ((GlobalSortMaxCountShuffleSpec) spec).getMaxPartitions() == 1;\n  }\n  return spec.canComputePartitionCount();\n}","tryCatchPattern":"try {\n  return spec.partitionCount();\n} catch (IllegalStateException e) {\n  return OptionalInt.empty(); // count determined at execution time\n}","preventionTips":["Call getMaxPartitions() instead of partitionCount() on max-count specs","Only call partitionCount() when maxPartitions == 1","Expect dynamic partition counts for multi-partition global-sort shuffles"],"tags":["msq","shuffle-spec","unknown-partition-count","internal-state"],"backgroundTag":"internal-invariant-violation","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"}