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
- Capture and store the id returned by Subscription::addDestination/removeDestination and use only that value.
- Consume each id once: stop polling after findDestinationResponse resolves it.
- Do not mix correlation ids between different Subscription or Publication instances.
- 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
- Only query ids returned by this Subscription's own addDestination/removeDestination
- Treat findDestinationResponse as one-shot per id
- Never reuse Publication ids for Subscription lookups
- Wrap lookups in try-catch in retry loops that may re-poll consumed ids
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)