aeron-io/aeron · error · ControlProtocolException

MALFORMED_COMMAND

MALFORMED_COMMAND

Error message

command={msgTypeId} too short: length={length}

What it means

The Aeron driver received a control-protocol command message whose total length is below the fixed MINIMUM_LENGTH for a destination (add/remove destination) message. DestinationMessageFlyweight.validateLength() is called by the driver on every incoming command; a too-short buffer means the message header is truncated or the wrong message type was sent, so the driver aborts processing with ControlProtocolException(MALFORMED_COMMAND).

Solutions

  1. Verify the Aeron client and driver (MediaDriver/SampleConfiguration) use the same Aeron version; upgrade both together.
  2. Check the code path that writes the destination command buffer to ensure it uses the flyweight's length computation instead of a hard-coded size.
  3. Enable Aeron logging / driver event log to inspect the raw command that arrived and confirm the length field.
  4. If writing a custom transport, ensure the full command frame (including channel string length and bytes) is written atomically without truncation.

Example fix

// before
buffer.putByte(0, ADD_DESTINATION);
buffer.putInt(4, partialLength); // hard-coded, may undershoot MINIMUM_LENGTH
// after
DestinationMessageFlyweight msg = new DestinationMessageFlyweight(buffer);
msg.destination(ADD_DESTINATION, destinationUri, streamId);
int length = DestinationMessageFlyweight.computeLength(destinationUri.length());
// publish exactly `length` bytes
Defensive patterns

Strategy: validation

Validate before calling

if (length < DestinationMessageFlyweight.MINIMUM_LENGTH) { throw new IllegalArgumentException("command too short: " + length); }

Try / catch

try { flyweight.validateLength(msgTypeId, length); } catch (ControlProtocolException e) { if (e.errorCode() == ControlProtocolException.MALFORMED_COMMAND) { log.error("Malformed control command, dropping", e); } else { throw e; } }

Prevention

When it happens

Trigger: Sending an ADD_DESTINATION / REMOVE_DESTINATION (or client-side generated) control command whose encoded byte length is less than MINIMUM_LENGTH, e.g. a hand-crafted or corrupted command buffer on the driver control stream, or a client/driver version mismatch producing a shorter message layout.

Common situations: Custom or older Aeron client talking to a newer driver with different message layout; byte-level corruption or truncation of the control command buffer; buggy third-party tooling that fabricates driver control commands; manually multiplexed command streams where a length header is wrong.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at aeron-client/src/main/java/io/aeron/command/DestinationMessageFlyweight.java:155

     *
     * @return length of the frame in bytes.
     */
    public int length()
    {
        return CHANNEL_OFFSET + lengthOfChannel;
    }

    /**
     * Validate buffer length is long enough for message.
     *
     * @param msgTypeId type of message.
     * @param length of message in bytes to validate.
     */
    public void validateLength(final int msgTypeId, final int length)
    {
        if (length < MINIMUM_LENGTH)
        {
            throw new ControlProtocolException(
                MALFORMED_COMMAND, "command=" + msgTypeId + " too short: length=" + length);
        }

        if ((length - MINIMUM_LENGTH) < buffer.getInt(offset + CHANNEL_OFFSET))
        {
            throw new ControlProtocolException(
                MALFORMED_COMMAND, "command=" + msgTypeId + " too short for channel: length=" + length);
        }
    }

    /**
     * Compute the length of the command message for a given channel length.
     *
     * @param channelLength to be appended to the header.
     * @return the length of the command message for a given channel length.
     */
    public static int computeLength(final int channelLength)
    {

View on GitHub (pinned to 6d60124e15)