aeron-io/aeron · error · IllegalArgumentException

Default header length not equal to HEADER_LENGTH: length=

Error message

Default header length not equal to HEADER_LENGTH: length={capacity}

What it means

storeDefaultFrameHeader copies the per-publication default frame header into the log metadata buffer, and it must be exactly HEADER_LENGTH (32 bytes on Aeron) long. When defaultHeader.capacity() differs, an IllegalArgumentException is thrown because a wrong-sized header would corrupt the framing of every data frame written to the log.

Solutions

  1. Allocate the default header buffer with exactly LogBufferDescriptor.HEADER_LENGTH capacity (e.g. new UnsafeBuffer(ByteBuffer.allocateDirect(LogBufferDescriptor.HEADER_LENGTH)))
  2. Build the header via DataHeaderFlyweight.DEFAULT_HEADER_DEFAULT or DataHeaderFlyweight.createDefaultHeader(...) which produce correctly sized buffers
  3. Check defaultHeader.capacity() == LogBufferDescriptor.HEADER_LENGTH before calling storeDefaultFrameHeader

Example fix

// before
final UnsafeBuffer header = new UnsafeBuffer(new byte[64]);
LogBufferDescriptor.storeDefaultFrameHeader(metaBuffer, header);
// after
final UnsafeBuffer header = new UnsafeBuffer(ByteBuffer.allocateDirect(LogBufferDescriptor.HEADER_LENGTH));
LogBufferDescriptor.storeDefaultFrameHeader(metaBuffer, header);
Defensive patterns

Strategy: validation

Validate before calling

if (defaultHeader.capacity() != LogBufferDescriptor.HEADER_LENGTH) { throw new IllegalArgumentException("default header must be HEADER_LENGTH=" + LogBufferDescriptor.HEADER_LENGTH); }

Try / catch

try { LogBufferDescriptor.storeDefaultFrameHeader(metaBuffer, defaultHeader); } catch (final IllegalArgumentException ex) { if (ex.getMessage().startsWith("Default header length not equal")) { /* rebuild header via DataHeaderFlyweight */ } throw ex; }

Prevention

When it happens

Trigger: Calling LogBufferDescriptor.storeDefaultFrameHeader with a DirectBuffer whose capacity is not HEADER_LENGTH (e.g. 36 or 24 bytes), typically when constructing a custom default header for a Publication or when allocating the header buffer with the wrong constant.

Common situations: Custom protocol/instance-id headers built with DataHeaderFlyweight but sized incorrectly, refactoring that changed HEADER_LENGTH assumptions between Aeron versions, or manually sized UnsafeBuffer allocations.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at aeron-client/src/main/java/io/aeron/logbuffer/LogBufferDescriptor.java:841

     * @return the total length of the log file.
     */
    public static long computeLogLength(final int termLength, final int filePageSize)
    {
        return align((PARTITION_COUNT * (long)termLength) + LOG_META_DATA_LENGTH, filePageSize);
    }

    /**
     * Store the default frame header to the log metadata buffer.
     *
     * @param metadataBuffer into which the default headers should be stored.
     * @param defaultHeader  to be stored.
     * @throws IllegalArgumentException if the defaultHeader larger than {@link #LOG_DEFAULT_FRAME_HEADER_MAX_LENGTH}.
     */
    public static void storeDefaultFrameHeader(final UnsafeBuffer metadataBuffer, final DirectBuffer defaultHeader)
    {
        if (defaultHeader.capacity() != HEADER_LENGTH)
        {
            throw new IllegalArgumentException(
                "Default header length not equal to HEADER_LENGTH: length=" + defaultHeader.capacity());
        }

        metadataBuffer.putInt(LOG_DEFAULT_FRAME_HEADER_LENGTH_OFFSET, HEADER_LENGTH);
        metadataBuffer.putBytes(LOG_DEFAULT_FRAME_HEADER_OFFSET, defaultHeader, 0, HEADER_LENGTH);
    }

    /**
     * Get a wrapper around the default frame header from the log metadata.
     *
     * @param metadataBuffer containing the raw bytes for the default frame header.
     * @return a buffer wrapping the raw bytes.
     */
    public static UnsafeBuffer defaultFrameHeader(final UnsafeBuffer metadataBuffer)
    {
        return new UnsafeBuffer(metadataBuffer, LOG_DEFAULT_FRAME_HEADER_OFFSET, HEADER_LENGTH);
    }

View on GitHub (pinned to 6d60124e15)