nathanmarz/storm · error · FailedException
Received commit for different transaction attempt
Error message
Received commit for different transaction attempt
What it means
During Trident batch processing, the commit stream delivers a TransactionAttempt that must match the attempt the executor recorded for that transaction id. If the attempt on the commit stream differs from the one stored in _activeBatches, the batch state is inconsistent (e.g. a replay with a new attempt id) and Trident throws FailedException so the batch is replayed.
Solutions
- Let the FailedException propagate — Trident will replay the batch with the correct attempt
- Verify the spout/emitter are stateless and correctly re-registered attempts after restart
- Check MasterBatchCoordinator zk state for stale transaction metadata and ensure only one topology uses the same state location
Defensive patterns
Strategy: try-catch
Try / catch
// Trident worker: FailedException marks batch for replay
try {
executor.execute(tuple);
} catch (FailedException e) {
LOG.warn("Commit attempt mismatch; batch will be replayed", e);
// do not ack; let Trident replay with the correct attempt
} Prevention
- Keep spout emitter stateless so replays are idempotent
- Avoid sharing zk transaction state between topologies
- Ensure topology.name and state locations stay stable across restarts
When it happens
Trigger: A commit tuple arrives on MasterBatchCoordinator.COMMIT_STREAM_ID whose TransactionAttempt does not equal the active attempt registered for the same transaction id — typically after topology restarts/replays where the spout re-emits a transaction with a different attempt number.
Common situations: Topology rebalanced or restarted mid-transaction; expired messages causing rebroadcast with a new attempt; misbehaving custom spout emitting mismatched attempts.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Current batch (
- Trying to select non-existent field
- Regular rich spouts not supported yet... try wrapping in a…
- Cannot join DRPC stream with streams originating from other…
- Parallelism is fixed to
AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12).
Data as JSON: /api/errors/ddddce9c040e3d7c.
Report an issue: GitHub.
Appendix: source
Thrown at storm-core/src/jvm/storm/trident/spout/TridentSpoutExecutor.java:73
_streamName = streamName;
}
@Override
public void prepare(Map conf, TopologyContext context, BatchOutputCollector collector) {
_emitter = _spout.getEmitter(_txStateId, conf, context);
_collector = new AddIdCollector(_streamName, collector);
}
@Override
public void execute(BatchInfo info, Tuple input) {
// there won't be a BatchInfo for the success stream
TransactionAttempt attempt = (TransactionAttempt) input.getValue(0);
if(input.getSourceStreamId().equals(MasterBatchCoordinator.COMMIT_STREAM_ID)) {
if(attempt.equals(_activeBatches.get(attempt.getTransactionId()))) {
((ICommitterTridentSpout.Emitter) _emitter).commit(attempt);
_activeBatches.remove(attempt.getTransactionId());
} else {
throw new FailedException("Received commit for different transaction attempt");
}
} else if(input.getSourceStreamId().equals(MasterBatchCoordinator.SUCCESS_STREAM_ID)) {
// valid to delete before what's been committed since
// those batches will never be accessed again
_activeBatches.headMap(attempt.getTransactionId()).clear();
_emitter.success(attempt);
} else {
_collector.setBatch(info.batchId);
_emitter.emitBatch(attempt, input.getValue(1), _collector);
_activeBatches.put(attempt.getTransactionId(), attempt);
}
}
@Override
public void cleanup() {
_emitter.close();
}
View on GitHub (pinned to cdb116e942)