aeron-io/aeron · error · IllegalArgumentException

EINVAL

EINVAL

Error message

unknown action

What it means

Thrown by ControlledFragmentAssembler::handlerCallback when the ControlledPollAction produced by the user's controlled fragment handler does not map to any known aeron_controlled_fragment_handler_action_t value. The switch over ABORT/COMMIT/BREAK/CONTINUE falls through and the wrapper treats it as an internal invariant violation. This means the handler returned an out-of-range or corrupted action value.

Solutions

  1. Audit your controlled fragment handler and ensure every return path yields a defined ControlledPollAction (ABORT, COMMIT, BREAK, CONTINUE).
  2. Initialize the action variable before returning it; never cast raw ints to ControlledPollAction.
  3. Rebuild all handler code with the same Aeron wrapper version as the library you link.
  4. If wrapping a C handler (handlerCallback path), verify the C handler only returns AERON_ACTION_* constants.

Example fix

// before
ControlledPollAction act; // uninitialized
if (cond) act = ControlledPollAction::BREAK;
return act;
// after
if (cond) return ControlledPollAction::BREAK;
return ControlledPollAction::CONTINUE; // always return a defined value
Defensive patterns

Strategy: validation

Validate before calling

ControlledPollAction sanitize(ControlledPollAction a) {
  switch (a) {
    case ControlledPollAction::ABORT:
    case ControlledPollAction::COMMIT:
    case ControlledPollAction::BREAK:
    case ControlledPollAction::CONTINUE:
      return a;
    default:
      return ControlledPollAction::CONTINUE;
  }
}

Type guard

bool isDefinedAction(ControlledPollAction a) {
  switch (a) {
    case ControlledPollAction::ABORT:
    case ControlledPollAction::COMMIT:
    case ControlledPollAction::BREAK:
    case ControlledPollAction::CONTINUE:
      return true;
    default:
      return false;
  }
}

Try / catch

try { subscription.controlledPoll(handler); }
catch (const aeron::util::IllegalArgumentException& e) {
  if (std::string(e.what()) == "unknown action") {
    log("handler returned undefined ControlledPollAction");
  }
}

Prevention

When it happens

Trigger: A controlledFragmentHandler returning a ControlledPollAction value not covered by the switch (e.g. an uninitialized enum, a cast integer, or a newly added enum value handled by an older wrapper binary).

Common situations: Mixing wrapper header versions with compiled handler code where ControlledPollAction gained new enumerators, casting raw ints to ControlledPollAction, or an uninitialized action variable in a custom handler.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at aeron-client/src/main/cpp_wrapper/ControlledFragmentAssembler.h:119

        ControlledPollAction action = assembler->m_delegate(bufferWrapper, 0, (util::index_t)length, headerWrapper);

        switch (action)
        {
            case ControlledPollAction::ABORT:
                return AERON_ACTION_ABORT;
                break;
            case ControlledPollAction::BREAK:
                return AERON_ACTION_BREAK;
                break;
            case ControlledPollAction::COMMIT:
                return AERON_ACTION_COMMIT;
                break;
            case ControlledPollAction::CONTINUE:
                return AERON_ACTION_CONTINUE;
                break;
        }

        throw IllegalArgumentException("unknown action", SOURCEINFO, EINVAL);
    }

    ControlledPollAction onFragment(AtomicBuffer &buffer, util::index_t offset, util::index_t length, Header &header)
    {
        aeron_controlled_fragment_handler_action_t action = aeron_controlled_fragment_assembler_handler(
            m_fragment_assembler,
            buffer.buffer() + offset,
            length,
            header.hdr());

        switch (action)
        {
            case AERON_ACTION_ABORT:
                return ControlledPollAction::ABORT;
                break;
            case AERON_ACTION_BREAK:
                return ControlledPollAction::BREAK;
                break;

View on GitHub (pinned to 6d60124e15)