apache/cassandra · error · MarshalException

Invalid remaining data after end of

Error message

Invalid remaining data after end of %s value

What it means

After unpacking all declared components of a tuple/UDT, TupleType checks that no leftover bytes remain in the buffer. If position < length, the value has more data than the type declares components, so unpack throws this MarshalException. It guards against reading a value serialized for a type with more fields than the current definition.

Solutions

  1. Confirm the reading type matches the schema that serialized the value (same number of fields)
  2. Migrate/rewrite rows written under the old wider UDT definition
  3. Re-serialize the value from its parsed fields instead of reusing the raw buffer
  4. If intentional cross-version data, handle the old format explicitly before calling unpack
Defensive patterns

Strategy: validation

Validate before calling

if (buf.remaining() > tupleType.serializedSize(...))
    throw new IllegalArgumentException("value longer than declared tuple serialization");

Try / catch

try {
    tupleType.unpack(buf);
} catch (MarshalException e) {
    // leftover bytes: schema mismatch between reader and writer
    log.error("Tuple type mismatch: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling unpack/elements/components on a serialized value that contains extra trailing bytes beyond the last declared component — e.g. a tuple written with N+1 fields then read as an N-field tuple after a schema downgrade, or concatenating wrong buffers.

Common situations: UDT/tuple schema evolved to fewer fields while old rows still hold the wider serialization; manual blob assembly mistakes; reading data from another cluster with a different UDT definition.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/15cb5c79f32c0a64. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/db/marshal/TupleType.java:337

            position += 4;

            // size < 0 means null value
            if (size >= 0)
            {
                if (length - position < size)
                    throw new MarshalException(String.format("Not enough bytes to read %dth %s", i, componentOrFieldName(i)));

                components.add(accessor.slice(value, position, size));
                position += size;
            }
            else
                components.add(null);
        }

        // error out if we got more values in the tuple/UDT than we expected
        if (position < length)
        {
            throw new MarshalException(String.format("Invalid remaining data after end of %s value", isTuple() ? "tuple" : "UDT"));
        }

        return components;
    }

    /**
     * Returns the name used for the specified component or field if the type is a Tuple.
     * @param i the component/field index
     * @return the name used for the specified component or field if the type is a Tuple.
     */
    protected String componentOrFieldName(int i)
    {
        return "component";
    }

    public static <V> V pack(ValueAccessor<V> accessor, V... components)
    {
        return pack(accessor, Arrays.asList(components));

View on GitHub (pinned to 88fd0f6a0e)