aeron-io/aeron · error · UnknownSubscriptionException

no subscription for stream

Error message

no subscription for stream ${streamId}

What it means

DataPacketDispatcher.removeSubscription(streamId) throws UnknownSubscriptionException when there is no registered stream-level interest for the given streamId. The driver never saw a matching wildcard subscription for that stream.

Solutions

  1. Verify the streamId matches an existing subscription before removal
  2. Track removal so each subscription is removed exactly once
  3. Catch UnknownSubscriptionException and treat it as idempotent cleanup if double-removal is expected

Example fix

// before
dispatcher.removeSubscription(streamId); // throws if already removed
// after
if (dispatcher.hasSubscription(streamId)) { dispatcher.removeSubscription(streamId); }
Defensive patterns

Strategy: try-catch

Validate before calling

// track live streamIds your client registered
if (!registeredStreamIds.contains(streamId)) return;

Try / catch

try { dispatcher.removeSubscription(streamId); } catch (UnknownSubscriptionException e) { /* already removed; ignore */ }

Prevention

When it happens

Trigger: Calling DriverConductor/client API to remove a subscription (with only streamId, i.e. all-sessions interest) when no subscription with that streamId is registered in the dispatcher.

Common situations: Double-close of a subscription, closing a subscription on the wrong streamId, or a race where the subscription was already removed by another path.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/10494fda82bafa8b. Report an issue: GitHub.

Appendix: source

Thrown at aeron-driver/src/main/java/io/aeron/driver/DataPacketDispatcher.java:185

        final SessionState sessionState = streamInterest.sessionInterestByIdMap.get(sessionId);
        if (NO_INTEREST == sessionState)
        {
            streamInterest.sessionInterestByIdMap.remove(sessionId);
        }
    }

    /**
     * Remove a subscription for a previously registered given stream id and wildcard session id.
     *
     * @param streamId to remove the capture for.
     */
    public void removeSubscription(final int streamId)
    {
        final StreamInterest streamInterest = streamInterestByIdMap.get(streamId);
        if (null == streamInterest)
        {
            throw new UnknownSubscriptionException("no subscription for stream " + streamId);
        }

        streamInterest.removeNonSessionSpecificInterest();

        streamInterest.isAllSessions = false;

        if (streamInterest.subscribedSessionIds.isEmpty())
        {
            streamInterestByIdMap.remove(streamId);
        }
    }

    /**
     * Remove a subscription for a previously registered given stream id and session id.
     *
     * @param streamId  to remove the capture for.
     * @param sessionId within the given stream id.
     */

View on GitHub (pinned to 6d60124e15)