aeron-io/aeron · error · AeronException
spies can not reject images
Error message
spies can not reject images
What it means
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.
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
Example fix
// before
image.rejectImage(correlationId, position, "not authorised");
// after
if (!subscription.channel().startsWith(Subscription.SPY_PREFIX))
{
image.rejectImage(correlationId, position, "not authorised");
}
else
{
// handle spy channel another way, e.g. stop polling
} Defensive patterns
Strategy: validation
Validate before calling
if (subscription.channel().startsWith("aeron:spy")) { throw new UnsupportedOperationException("rejectImage not supported on spy subscriptions"); } Type guard
boolean supportsRejectImage(Subscription s) { return !s.channel().startsWith(Subscription.SPY_PREFIX); } Try / catch
try { image.rejectImage(correlationId, position, reason); } catch (AeronException e) { if (e.getMessage().contains("spies")) { applyAlternativeBackpressure(image); } else { throw e; } } Prevention
- 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
When it happens
Trigger: Calling image.rejectImage(correlationId, position, reason) (or subscription.rejectImage) on an Image obtained from a Subscription whose channel is "aeron:spy?...".
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- failed to send start recording request
- failed to send extend recording request
- failed to send stop recording request
- IPC merging is not supported
- Driver events adapter is invalid
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/f5a843960080b1c4.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-client/src/main/java/io/aeron/Subscription.java:638
i++;
}
if (null != removedImage)
{
removedImage.close();
images = oldArray.length == 1 ? EMPTY_IMAGES : ArrayUtil.remove(oldArray, i);
conductor.releaseLogBuffers(removedImage.logBuffers(), correlationId, NULL_VALUE);
}
return removedImage;
}
void rejectImage(final long correlationId, final long position, final String reason)
{
if (channel().startsWith(SPY_PREFIX))
{
throw new AeronException("spies can not reject images");
}
conductor.rejectImage(correlationId, position, reason);
}
/**
* {@inheritDoc}
*/
@Override
public String toString()
{
return "Subscription{" +
"registrationId=" + registrationId +
", isClosed=" + isClosed +
", isConnected=" + isConnected() +
", streamId=" + streamId +
", channel='" + channel + '\'' +
", localSocketAddresses=" + localSocketAddresses() +View on GitHub (pinned to 6d60124e15)