aeron-io/aeron · critical · AgentTerminationException
failed to start clustered service(s)
Error message
failed to start clustered service(s)
What it means
During startup the consensus module waits for each clustered service's initial ack. If polled ServiceAcks contain null relevantIds (service never sent its initial ack), AgentTerminationException is thrown because the cluster cannot start without all services reporting readiness.
Solutions
- Inspect ctx.errorLog() written by areAllRelevantIdsNonNull for which service failed
- Check each clustered service's own logs for startup exceptions in onStart
- Verify serviceCount and serviceId configuration match the deployed containers
- Ensure service containers run the same Aeron version as the consensus module; restart the cluster
Example fix
// before: service crashing in onStart so its ack never arrives
public void onStart(Cluster cluster, Image snapshotImage) { throw new RuntimeException(...); }
// after: fail fast with a clear message and correct startup
public void onStart(Cluster cluster, Image snapshotImage)
{
// validate dependencies before marking ready
this.store = openStore(); // throws descriptive error if unavailable
} Defensive patterns
Strategy: validation
Validate before calling
// before starting the cluster, ensure all services are resolvable
for (ClusteredService service : services)
{
Objects.requireNonNull(service, "null ClusteredService in configuration");
} Try / catch
catch (AgentTerminationException e)
{
if (e.getMessage().contains("failed to start clustered service"))
{
// consult ctx.errorLog() written by ServiceAck.areAllRelevantIdsNonNull
log.error("a service never acked startup; check service container logs", e);
}
throw e;
} Prevention
- Test each service's onStart in isolation before cluster launch
- Match serviceCount and serviceIds across cluster and containers
- Pin the same Aeron version in cluster and service containers
- Add startup timeouts and logging inside service onStart implementations
When it happens
Trigger: Thrown when ServiceAck.areAllRelevantIdsNonNull fails after polling serviceAckQueues during cluster start, i.e. at least one service did not deliver its initial ack (ackId 0) in time.
Common situations: A service container crashed on startup (class not found, init exception); wrong service count or serviceId configuration; services blocked in their onStart; version mismatch between cluster and service containers.
Related errors
- initial ack already received from service: possible…
- not found in
- ${eventCode}: ${detail}
- clusterMembers and endpoints differ
- response publication already added
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/e63a5fb11ec52acc.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleAgent.java:3526
if (!recoveryPlan.snapshots().isEmpty())
{
loadSnapshot(recoveryPlan.snapshots().get(0), archive);
}
else if (null != consensusModuleExtension)
{
consensusModuleExtension.onStart(this, null);
}
idleStrategy.reset();
while (!ServiceAck.hasReached(expectedAckPosition, serviceAckId, serviceAckQueues))
{
idle(consensusModuleAdapter.poll());
}
final ServiceAck[] serviceAcks = ServiceAck.pollServiceAcks(serviceAckQueues);
if (!ServiceAck.areAllRelevantIdsNonNull("failed to start clustered service", serviceAcks, ctx.errorLog()))
{
throw new AgentTerminationException("failed to start clustered service(s)");
}
captureServiceClientIds(serviceAcks);
++serviceAckId;
}
return recoveryPlan;
}
private RecordingLog.RecoveryPlan recoverFromBootstrapState()
{
final ConsensusModuleStateExport bootstrapState = ctx.bootstrapState();
logRecordingId(bootstrapState.logRecordingId);
final RecordingLog.RecoveryPlan recoveryPlan = recordingLog.createRecoveryPlan(
archive, serviceCount, logRecordingId);
expectedAckPosition = bootstrapState.expectedAckPosition;View on GitHub (pinned to 6d60124e15)