nathanmarz/storm · warning
Failed to get metadata for a transaction
Error message
Failed to get metadata for a transaction
What it means
TransactionalSpoutCoordinator.sync() catches FailedException thrown while obtaining transaction metadata from the coordinator and logs 'Failed to get metadata for a transaction'. Unlike the batch executor, it only logs — no tuple is failed — so sync aborts for this pass and the coordinator simply retries on the next nextTuple/ack/fail driven sync. A persistent underlying failure means no new transaction batches are emitted.
Solutions
- Inspect the logged FailedException stack trace to find the metadata source that failed (usually ZooKeeper or a custom store).
- Restore/verify the metadata backend (ZK quorum health, connectivity, permissions).
- Add defensive retry/backoff in getMetadata for transient backend errors so sync can recover on its own.
- Check the coordinator's state in ZooKeeper for corruption; reset transaction state if safe.
- If failures persist, restart the coordinator task / topology after fixing the backend.
Example fix
// before
public Map<String, Object> getMetadata(TransactionAttempt tx) {
return zkClient.readData(path); // transient ZK error -> FailedException each sync
}
// after
public Map<String, Object> getMetadata(TransactionAttempt tx) {
for (int i = 0; i < 3; i++) {
try { return zkClient.readData(path); }
catch (Exception e) { sleep(backoff(i)); }
}
throw new FailedException("metadata unavailable after retries");
} Defensive patterns
Strategy: retry
Validate before calling
// before relying on coordinator metadata, verify the backend is reachable
if (!zkClientExists(coordinatorStatePath)) { throw new IllegalStateException("coordinator metadata store unavailable: " + coordinatorStatePath); } Try / catch
public Map<String,Object> getMetadata(TransactionAttempt tx) {
try {
return readMetadata(tx);
} catch (TransientBackendException e) {
throw new FailedException(e); // sync() logs and retries on next nextTuple/ack/fail
}
} Prevention
- Ensure the metadata store (usually ZooKeeper) is healthy and sized for the cluster.
- Implement bounded retry/backoff inside coordinator getMetadata.
- Alert on repeated 'Failed to get metadata' warnings — they mean no new batches are emitted.
- Keep coordinator transaction state clean; verify after hard crashes or manual ZK edits.
When it happens
Trigger: The coordinator's getMetadata/initializeTransaction path throws FailedException (e.g. metadata store read failure) while sync() is advancing _currTransaction and emitting TRANSACTION_BATCH_STREAM tuples; called from nextTuple, ack, or fail.
Common situations: Zookeeper or external metadata store unreachable; coordinator code throwing FailedException for transient backend errors; network partition between the coordinator task and its metadata backend; corrupted coordinator state causing repeated metadata fetch failures.
Related errors
- Trying to initialize transaction for which there should be…
- Expecting previous txid state to be the previous transaction
- Expecting tx state to be initialized in strict order but…
- Failed to emit batch for transaction
- Each element of the list
AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12).
Data as JSON: /api/errors/ddc004d0baf2c188.
Report an issue: GitHub.
Appendix: source
Thrown at storm-core/src/jvm/backtype/storm/transactional/TransactionalSpoutCoordinator.java:160
_collector.emit(TRANSACTION_COMMIT_STREAM_ID, new Values(maybeCommit.attempt), maybeCommit.attempt);
}
try {
if(_activeTx.size() < _maxTransactionActive) {
BigInteger curr = _currTransaction;
for(int i=0; i<_maxTransactionActive; i++) {
if((_coordinatorState.hasCache(curr) || _coordinator.isReady())
&& !_activeTx.containsKey(curr)) {
TransactionAttempt attempt = new TransactionAttempt(curr, _rand.nextLong());
Object state = _coordinatorState.getState(curr, _initializer);
_activeTx.put(curr, new TransactionStatus(attempt));
_collector.emit(TRANSACTION_BATCH_STREAM_ID, new Values(attempt, state, previousTransactionId(_currTransaction)), attempt);
}
curr = nextTransactionId(curr);
}
}
} catch(FailedException e) {
LOG.warn("Failed to get metadata for a transaction", e);
}
}
@Override
public Map<String, Object> getComponentConfiguration() {
Config ret = new Config();
ret.setMaxTaskParallelism(1);
return ret;
}
private static enum AttemptStatus {
PROCESSING,
PROCESSED,
COMMITTING
}
private static class TransactionStatus {
TransactionAttempt attempt;View on GitHub (pinned to cdb116e942)