{"record":{"id":"6ae36a768a4d8dd5","repo":"aeron-io/aeron","slug":"serviceid-serviceid-invalid-for-servicecount-servicecount","errorCode":null,"errorMessage":"serviceId=<serviceId> invalid for serviceCount=<serviceCount>","messagePattern":"serviceId=<serviceId> invalid for serviceCount=<serviceCount>","errorType":"exception","errorClass":"ClusterException","httpStatus":null,"severity":"error","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleAgent.java","lineNumber":729,"sourceCode":"        if (pendingServiceMessageTrackers.length > 0)\n        {\n            pendingServiceMessageTrackers[0].loadState(\n                nextServiceSessionId, logServiceSessionId, pendingMessageCapacity);\n        }\n    }\n\n    public void onLoadPendingMessageTracker(\n        final long nextServiceSessionId,\n        final long logServiceSessionId,\n        final int pendingMessageCapacity,\n        final int serviceId,\n        final DirectBuffer buffer,\n        final int offset,\n        final int length)\n    {\n        if (serviceId < 0 || serviceId >= pendingServiceMessageTrackers.length)\n        {\n            throw new ClusterException(\n                \"serviceId=\" + serviceId + \" invalid for serviceCount=\" + pendingServiceMessageTrackers.length);\n        }\n\n        pendingServiceMessageTrackers[serviceId].loadState(\n            nextServiceSessionId, logServiceSessionId, pendingMessageCapacity);\n    }\n\n    public void onLoadPendingMessage(\n        final long clusterSessionId, final DirectBuffer buffer, final int offset, final int length)\n    {\n        final int serviceId = PendingServiceMessageTracker.serviceIdFromLogMessage(clusterSessionId);\n        pendingServiceMessageTrackers[serviceId].appendMessage(buffer, offset, length);\n    }\n\n    public void onLoadTimer(\n        final long correlationId, final long deadline, final DirectBuffer buffer, final int offset, final int length)\n    {\n        onScheduleTimer(correlationId, deadline);","sourceCodeStart":711,"sourceCodeEnd":747,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleAgent.java#L711-L747","documentation":"When loading service message tracker state from a snapshot, the serviceId index must fall within the configured serviceCount (pendingServiceMessageTrackers array length). A serviceId outside [0, serviceCount) indicates the snapshot was produced by a cluster with more services than this node is configured for.","triggerScenarios":"onServiceMessageTracker loading state where serviceId < 0 or >= pendingServiceMessageTrackers.length, typically because the snapshot contains entries for services that no longer exist under the current serviceCount configuration.","commonSituations":"Reducing the number of clustered services without regenerating the snapshot; a snapshot produced with a different aeron.cluster.service.count; corrupted or hand-edited snapshot data.","solutions":["Set the cluster's serviceCount to match the snapshot (the service count that produced it).","Take a fresh snapshot with the reduced service count before removing services.","Regenerate/rebuild cluster state if services were removed and no compatible snapshot exists.","Validate snapshot contents when migrating state between clusters with different service topologies."],"exampleFix":"// before\nctx.serviceCount(2); // snapshot has 3 services\n// after\nctx.serviceCount(3); // matches snapshot, then snapshot again after removing a service","handlingStrategy":"validation","validationCode":"// before load\nif (configuredServiceCount < snapshotServiceCount) {\n    throw new IllegalStateException(\"serviceCount \" + configuredServiceCount + \" smaller than snapshot's \" + snapshotServiceCount);\n}","typeGuard":null,"tryCatchPattern":"try { cluster.start(); } catch (ClusterException e) { if (e.getMessage().contains(\"invalid for serviceCount\")) { raiseServiceCountOrRestoreSnapshot(); } else { throw e; } }","preventionTips":["Snapshot before changing service count, in both directions.","Keep aeron.cluster.service.count stable across snapshot load.","Validate snapshot metadata when migrating between clusters."],"tags":["snapshot","service-count","configuration","bounds"],"backgroundTag":"value-out-of-range","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}