{"record":{"id":"fefb15acf33f7cf1","repo":"aeron-io/aeron","slug":"registration-id-is-not-a-counter-simplename","errorCode":null,"errorMessage":"registration id is not a Counter: <simpleName>","messagePattern":"registration id is not a Counter: <simpleName>","errorType":"exception","errorClass":"AeronException","httpStatus":null,"severity":"error","filePath":"aeron-client/src/main/java/io/aeron/ClientConductor.java","lineNumber":1376,"sourceCode":"        }\n    }\n\n    void asyncRemoveCounter(final long counterRegistrationId)\n    {\n        clientLock.lock();\n        try\n        {\n            if (NULL_VALUE == counterRegistrationId || isTerminating || isClosed)\n            {\n                return;\n            }\n\n            ensureNotReentrant();\n\n            final Object resource = resourceByRegIdMap.get(counterRegistrationId);\n            if (null != resource && !(resource instanceof Counter))\n            {\n                throw new AeronException(\"registration id is not a Counter: \" +\n                    resource.getClass().getSimpleName());\n            }\n\n            final Counter counter = (Counter)resource;\n            if (null != counter)\n            {\n                resourceByRegIdMap.remove(counterRegistrationId);\n                counter.internalClose();\n            }\n\n            if (asyncCommandIdSet.remove(counterRegistrationId) || null != counter)\n            {\n                asyncCommandIdSet.add(driverProxy.removeCounter(counterRegistrationId));\n            }\n        }\n        finally\n        {\n            clientLock.unlock();","sourceCodeStart":1358,"sourceCodeEnd":1394,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-client/src/main/java/io/aeron/ClientConductor.java#L1358-L1394","documentation":"ClientConductor.releaseCounter (or equivalent lookup by registration id) fetches the resource from resourceByRegIdMap and, if a resource exists that is not a Counter, throws AeronException naming its simple class name. The registration id you supplied identifies a different client resource type (e.g. a Publication, Subscription, or Image), and releasing it through the Counter API would corrupt the conductor's bookkeeping.","triggerScenarios":"Calling AeronClient/aeron.releaseCounter(counterRegistrationId) or ClientConductor's Counter release path with a registration id that actually belongs to a Publication, ExclusivePublication, Subscription, or Image registered on the same client.","commonSituations":"Mixing up correlation ids collected from async addPublication/addCounter commands in a shared registry; passing an image or subscription id saved from a callback; refactors that unify resource ids into one map/array and index into the wrong slot; copy-paste between release calls.","solutions":["Ensure you pass the registration id returned by addCounter (or Counter.registrationId()), not another resource's id.","Separate your bookkeeping for publication/subscription/counter ids (distinct fields or maps) instead of one pooled collection.","Check the id at the call site: log or assert which resource it came from before releasing.","Prefer calling counter.close() on the Counter object, which routes through the correct release path."],"exampleFix":"// before\nlong id = idsFromAsyncCommands.get(\"resource\"); // could be a publication id\naeronClient.releaseCounter(id);\n// throws AeronException: registration id is not a Counter\n\n// after\nCounter counter = countersById.get(registrationId);\nif (counter != null) {\n    counter.close(); // releases via the correct path\n}","handlingStrategy":"type-guard","validationCode":"if (!(aeronClient.getResource(registrationId) instanceof Counter)) {\n    throw new IllegalStateException(\"id \" + registrationId + \" is not a Counter\");\n}","typeGuard":"boolean isCounterRegId(long registrationId) {\n    Object r = resourceByRegIdMap.get(registrationId); // or your own registry\n    return r instanceof Counter;\n}","tryCatchPattern":"try {\n    aeronClient.releaseCounter(registrationId);\n} catch (AeronException e) {\n    if (e.getMessage().startsWith(\"registration id is not a Counter\")) {\n        logger.error(\"wrong resource id {} passed to releaseCounter\", registrationId, e);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Store Counter registration ids separately from publication/subscription ids","Call counter.close() on the Counter object rather than releasing by raw id","Log the resource type whenever you record a registration id","Keep one source of truth for ids returned by each add* call"],"tags":["aeron","counter","resource-lifecycle","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}