nathanmarz/storm · error · RuntimeException

Parallelism is fixed to

Error message

Parallelism is fixed to ${fixedP} but max parallelism is less than that: ${maxP}

What it means

When Trident groups nodes with equivalent parallelism (computeSourcedGroups/equiv groups), each group must have a satisfiable parallelism. If a group's parallelism is pinned by a state's requiredNumPartitions (fixedP) and some node also declares a max parallelism hint (maxP) smaller than that fixed value, no valid parallelism exists and build throws this RuntimeException.

Solutions

  1. Raise the max parallelism hint so it is >= the state's requiredNumPartitions
  2. Lower or remove the state's requiredNumPartitions constraint
  3. Remove the conflicting parallelismHint so the group takes the fixed parallelism
  4. Refactor topology so the state-anchored nodes are not in the same equivalence group

Example fix

// before
state.newValuesStream().parallelismHint(2); // state requires 4 partitions
// after
state.newValuesStream().parallelismHint(4); // max >= fixed required partitions
Defensive patterns

Strategy: validation

Validate before calling

// ensure max hint >= state requiredNumPartitions before build
if (fixedP != null && hint != null && hint < fixedP) {
    throw new IllegalArgumentException("parallelismHint must be >= state requiredNumPartitions " + fixedP);
}

Try / catch

try {
    topology.build();
} catch (RuntimeException e) {
    if (e.getMessage().contains("but max parallelism is less than that")) {
        throw new IllegalStateException("Raise parallelismHint to at least the state's requiredNumPartitions", e);
    } throw e;
}

Prevention

When it happens

Trigger: A topology where one equivalent-parallelism group contains a state spec requiring N partitions (e.g. memoryMapState/redis state with requiredNumPartitions=N) while another node in the same group has parallelismHint(max) with max < N.

Common situations: Adding parallelismHint to nodes connected to persistentAggregate state whose backing store fixes partition count; changing state backend requiredNumPartitions without updating parallelism hints; merging streams so previously separate groups become one equivalence group.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12). Data as JSON: /api/errors/8fc4db886ba300b3. Report an issue: GitHub.

Appendix: source

Thrown at storm-core/src/jvm/storm/trident/TridentTopology.java:599

        for(Group g: groups) {
            for(PartitionNode n: externalGroupInputs(g)) {
                if(isIdentityPartition(n)) {
                    Node parent = TridentUtils.getParent(graph, n);
                    Group parentGroup = grouper.nodeGroup(parent);
                    if(parentGroup!=null && !parentGroup.equals(g)) {
                        equivs.addEdge(parentGroup, g);
                    }
                }
            }            
        }
        
        Map<Group, Integer> ret = new HashMap();
        List<Set<Group>> equivGroups = new ConnectivityInspector<Group, Object>(equivs).connectedSets();
        for(Set<Group> equivGroup: equivGroups) {
            Integer fixedP = getFixedParallelism(equivGroup);
            Integer maxP = getMaxParallelism(equivGroup);
            if(fixedP!=null && maxP!=null && maxP < fixedP) {
                throw new RuntimeException("Parallelism is fixed to " + fixedP + " but max parallelism is less than that: " + maxP);
            }
            
            
            Integer p = 1;
            for(Group g: equivGroup) {
                for(Node n: g.nodes) {
                    if(n.parallelismHint!=null) {
                        p = Math.max(p, n.parallelismHint);
                    }
                }
            }
            if(maxP!=null) p = Math.min(maxP, p);
            
            if(fixedP!=null) p = fixedP;
            for(Group g: equivGroup) {
                ret.put(g, p);
            }
        }

View on GitHub (pinned to cdb116e942)