{"record":{"id":"f5a843960080b1c4","repo":"aeron-io/aeron","slug":"spies-can-not-reject-images","errorCode":null,"errorMessage":"spies can not reject images","messagePattern":"spies can not reject images","errorType":"exception","errorClass":"AeronException","httpStatus":null,"severity":"error","filePath":"aeron-client/src/main/java/io/aeron/Subscription.java","lineNumber":638,"sourceCode":"\n            i++;\n        }\n\n        if (null != removedImage)\n        {\n            removedImage.close();\n            images = oldArray.length == 1 ? EMPTY_IMAGES : ArrayUtil.remove(oldArray, i);\n            conductor.releaseLogBuffers(removedImage.logBuffers(), correlationId, NULL_VALUE);\n        }\n\n        return removedImage;\n    }\n\n    void rejectImage(final long correlationId, final long position, final String reason)\n    {\n        if (channel().startsWith(SPY_PREFIX))\n        {\n            throw new AeronException(\"spies can not reject images\");\n        }\n\n        conductor.rejectImage(correlationId, position, reason);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public String toString()\n    {\n        return \"Subscription{\" +\n            \"registrationId=\" + registrationId +\n            \", isClosed=\" + isClosed +\n            \", isConnected=\" + isConnected() +\n            \", streamId=\" + streamId +\n            \", channel='\" + channel + '\\'' +\n            \", localSocketAddresses=\" + localSocketAddresses() +","sourceCodeStart":620,"sourceCodeEnd":656,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-client/src/main/java/io/aeron/Subscription.java#L620-L656","documentation":"Aeron throws this from rejectImage() when the subscription's channel is a spy channel (starts with \"aeron:spy\"). Spy subscriptions read directly from a local publisher's shared memory rather than over the network, and the reject-image protocol (which tells a sender to stop sending) is only defined for real network subscriptions. Rejecting is not meaningful for a spy, so Aeron fails fast with AeronException.","triggerScenarios":"Calling image.rejectImage(correlationId, position, reason) (or subscription.rejectImage) on an Image obtained from a Subscription whose channel is \"aeron:spy?...\".","commonSituations":"Backpressure/abuse-control logic (e.g. rejecting a slow or unauthorized publisher) written generically for all subscriptions but deployed against an inter-process (IPC-over-shared-memory) spy channel in the same JVM/host; copy-pasted channel configs switching from udp to spy.","solutions":["Check subscription.channel().startsWith(\"aeron:spy\") (Subscription.SPY_PREFIX) before wiring rejectImage and skip it for spies","Enforce backpressure on spy consumers differently: slow the local publisher or stop polling, since rejection has no meaning in shared memory","Use a network (udp/ipc non-spy) channel if the reject-image semantics are actually required","Catch AeronException around rejectImage and fall back to simply not polling that image"],"exampleFix":"// before\nimage.rejectImage(correlationId, position, \"not authorised\");\n\n// after\nif (!subscription.channel().startsWith(Subscription.SPY_PREFIX))\n{\n    image.rejectImage(correlationId, position, \"not authorised\");\n}\nelse\n{\n    // handle spy channel another way, e.g. stop polling\n}","handlingStrategy":"validation","validationCode":"if (subscription.channel().startsWith(\"aeron:spy\")) { throw new UnsupportedOperationException(\"rejectImage not supported on spy subscriptions\"); }","typeGuard":"boolean supportsRejectImage(Subscription s) { return !s.channel().startsWith(Subscription.SPY_PREFIX); }","tryCatchPattern":"try { image.rejectImage(correlationId, position, reason); } catch (AeronException e) { if (e.getMessage().contains(\"spies\")) { applyAlternativeBackpressure(image); } else { throw e; } }","preventionTips":["Branch on channel type (spy vs network) before applying reject-based policies","Centralize reject logic in one utility that knows about SPY_PREFIX","Use polling pauses or publisher-side flow control for spy (IPC) consumers","Document that rejectImage applies only to network-bound subscriptions"],"tags":["ipc","unsupported-operation","messaging"],"backgroundTag":"unsupported-operation","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"}