aeron-io/aeron · error · IllegalArgumentException

EINVAL

EINVAL

Error message

Unknown correlation id

What it means

Thrown by Subscription::findDestinationResponse(correlationId) when the correlation id is absent from the subscription's m_pendingDestinations map. Only ids returned by this Subscription's async addDestination/removeDestination calls are valid, and each is resolved exactly once. Querying an unknown id raises IllegalArgumentException with EINVAL instead of a soft failure.

Solutions

  1. Capture and store the id returned by Subscription::addDestination/removeDestination and use only that value.
  2. Consume each id once: stop polling after findDestinationResponse resolves it.
  3. Do not mix correlation ids between different Subscription or Publication instances.
  4. If the id may be stale, catch IllegalArgumentException and re-issue the addDestination/removeDestination call.

Example fix

// before
subscription.findDestinationResponse(otherSubscriptionId); // wrong namespace
// after
long id = subscription.addDestination("aeron:udp?endpoint=localhost:40456");
if (subscription.findDestinationResponse(id)) { /* consume once */ }
Defensive patterns

Strategy: validation

Validate before calling

std::unordered_set<long> pendingSubIds;
long id = subscription.addDestination(uri);
pendingSubIds.insert(id);
// guard: if (!pendingSubIds.count(id)) return false; // skip lookup, re-add if needed

Try / catch

try {
  if (subscription.findDestinationResponse(id)) { pendingSubIds.erase(id); }
} catch (const aeron::util::IllegalArgumentException&) {
  log("stale subscription correlation id");
  id = subscription.addDestination(uri);
}

Prevention

When it happens

Trigger: Polling findDestinationResponse with an id never registered by this Subscription's addDestination/removeDestination, a duplicate poll of an already-consumed id, or cross-object id reuse.

Common situations: Applications that lose the id returned by async addDestination, retry logic that re-polls consumed ids, or confusion between Subscription and Publication correlation-id namespaces.

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/9f10ada1e30aca75. Report an issue: GitHub.

Appendix: source

Thrown at aeron-client/src/main/cpp_wrapper/Subscription.h:383

     *
     * - If the correlationId is unknown, then an exception is thrown.
     * - If the media driver has not answered the add/remove command, then a false is returned.
     * - If the media driver has successfully added or removed the destination then true is returned.
     * - If the media driver has returned an error, this method will throw the error returned.
     *
     * @see Subscription::addDestination
     * @see Subscription::removeDestination
     *
     * @param correlationId of the add/remove command returned by Subscription::addDestination
     * or Subscription::removeDestination
     * @return true for added or false if not.
     */
    bool findDestinationResponse(std::int64_t correlationId)
    {
        auto search = m_pendingDestinations.find(correlationId);
        if (search == m_pendingDestinations.end())
        {
            throw IllegalArgumentException("Unknown correlation id", SOURCEINFO, EINVAL);
        }

        auto async = search->second;
        try
        {
            bool result = findDestinationResponse(async);
            if (result)
            {
                m_pendingDestinations.erase(correlationId);
            }
            return result;
        }
        catch (...)
        {
            m_pendingDestinations.erase(correlationId);
            throw;
        }
    }

View on GitHub (pinned to 6d60124e15)