aeron-io/aeron · error

AERON_ERROR_CODE_MALFORMED_COMMAND

AERON_ERROR_CODE_MALFORMED_COMMAND

Error message

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

What it means

The C media driver's conductor command loop read a command whose record length is shorter than the minimum required for the given msg_type_id (or invalid overall). It sets AERON_ERROR_CODE_MALFORMED_COMMAND, logs 'command=%d too short: length=%llu', and skips the message by continuing the ring-buffer reader.

Solutions

  1. Restart both driver and clients with matching Aeron versions so record layouts agree.
  2. Remove stale shared-memory files (/dev/shm/aeron-*) and recreate them via a fresh driver start.
  3. Fix the producer to always write the full command record before committing the length/commit position.
  4. Check for compiler struct-packing or ABI differences if embedding the C driver/client in the same process.

Example fix

// before: committing before the payload is fully written
atomic_inc(&rb->tail, record_length);
// after: write full record, memory barrier, then commit length
memcpy(rec->data, cmd, cmd_len);
release_fence();
rec->length = (int32_t)record_length;
Defensive patterns

Strategy: try-catch

Validate before calling

size_t min_len = aeron_driver_command_min_length(msg_type_id); if (length < min_len) { fprintf(stderr, "refusing to send command %lld: len %llu < %zu\n", (long long)msg_type_id, length, min_len); abort(); }

Type guard

static bool command_record_is_complete(const uint8_t *rec, size_t len, size_t expected) { return len >= expected && rec != NULL; }

Try / catch

if (aeron_errcode() == -AERON_ERROR_CODE_MALFORMED_COMMAND) { fprintf(stderr, "malformed command in ring buffer: %s\n", aeron_errmsg()); /* halt writer, recreate buffers */ } else if (aeron_errcode() != 0) { fprintf(stderr, "aeron error: %s\n", aeron_errmsg()); }

Prevention

When it happens

Trigger: A writer advanced the ring buffer with a truncated record (wrote length header without the full payload), a corrupted /dev/shm file, or a client with mismatched struct packing/protocol version sending commands the driver considers too small.

Common situations: Crashed client leaving a partially written command; version mismatch between client and driver struct layouts; manual tooling or memory corruption modifying the shared-memory command buffer.

Related errors


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

Appendix: source

Thrown at aeron-driver/src/main/c/aeron_driver_conductor.c:3214

        }

        default:
            AERON_SET_ERR(-AERON_ERROR_CODE_UNKNOWN_COMMAND_TYPE_ID, "command=%d unknown", msg_type_id);
            aeron_driver_conductor_log_error(conductor);
            break;
    }

    if (result < 0)
    {
        aeron_driver_conductor_on_error(conductor, aeron_errcode(), aeron_errmsg(), correlation_id);
    }

    return AERON_RB_CONTINUE;

malformed_command:
    AERON_SET_ERR(
        -AERON_ERROR_CODE_MALFORMED_COMMAND, "command=%d too short: length=%" PRIu64, msg_type_id, (uint64_t)length);
    aeron_driver_conductor_log_error(conductor);

    return AERON_RB_CONTINUE;
}

void aeron_driver_conductor_on_command_queue(void *clientd, void *item)
{
    aeron_command_base_t *cmd = (aeron_command_base_t *)item;
    cmd->func(clientd, cmd);
}

void aeron_driver_conductor_on_check_for_blocked_driver_commands(aeron_driver_conductor_t *conductor, int64_t now_ns)
{
    int64_t consumer_position = aeron_mpsc_rb_consumer_position(&conductor->to_driver_commands);

    if (consumer_position == conductor->last_command_consumer_position &&
        aeron_mpsc_rb_producer_position(&conductor->to_driver_commands) > consumer_position)
    {
        int64_t position_change_deadline_ns = conductor->time_of_last_to_driver_position_change_ns +

View on GitHub (pinned to 6d60124e15)