apache/cassandra · error · MarshalException
Only complex cells should have a cell path
Error message
Only complex cells should have a cell path
What it means
Cassandra throws this MarshalException when deserializing/validating a cell that carries a CellPath (the per-cell component used by collections, UDTs and other multi-cell/complex types) but the column itself is not complex (single-cell). Only complex columns can have path components, so a path on a simple column indicates corrupt or malformed data.
Solutions
- Verify the column definition matches the data being read (a frozen column must not receive cells with paths); unfreeze/keep the column multi-cell if path-carrying data must be read.
- Run nodetool scrub / repairs on the affected table to drop or rewrite corrupt cells.
- If triggered by an ALTER, ensure the column was altered consistently on all nodes and migrate data with INSERT after the schema change instead of reading stale cells.
- If you construct cells programmatically (internal tooling), only set a CellPath for isComplex() columns.
Example fix
// before (writing a cell with a path for a frozen column)
Cell<Object> cell = BufferCell.live(column, ts, value, CellPath.create(b));
// after
Cell<Object> cell = column.isComplex()
? BufferCell.live(column, ts, value, CellPath.create(b))
: BufferCell.live(column, ts, value); Defensive patterns
Strategy: validation
Validate before calling
if (!column.isComplex() && cell.path() != null)
throw new IllegalArgumentException("Cell path set for non-complex column " + column.name); Type guard
boolean canHavePath(ColumnMetadata col) { return col.isComplex(); } Try / catch
try { /* deserialize/validate */ } catch (MarshalException e) {
logger.error("Corrupt cell for {}: {}", column.name, e.getMessage());
// trigger repair/scrub of the affected range
} Prevention
- Only attach CellPath to multi-cell (non-frozen collection/UDT) columns.
- After altering a column to frozen, rewrite data rather than reading stale cells.
- Schedule scrub/repair after schema migrations that change cell kind.
When it happens
Trigger: ColumnMetadata.validateCell() calls validateCellPath() with a non-null CellPath while isComplex() is false — e.g. deserializing a partition containing a cell with a path for a frozen/single-cell column, or after altering a column from a non-frozen collection to frozen (making it single-cell) while old cells with paths still exist.
Common situations: Reading SSTables or receiving mutations written before an ALTER TYPE / frozen conversion; hand-crafted or corrupted commit log/mutation data; schema changes that changed a column's cell kind without rewriting existing data.
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
- Corrupt flags value for clustering prefix (isStatic flag…
- Error decoding JSON:
- Error reading key in segment at position
- Invalid Columns subset bytes; too many bits set
- Invalid Columns subset bytes; too many bits set
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/0135f86a104fd930.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/schema/ColumnMetadata.java:683
}
else if(type.isUDT())
{
// To validate a non-frozen UDT field, both the path and the value
// are needed, the path being an index into an array of value types.
((UserType)type).validateCell(cell);
}
else
{
type.validateCellValue(cell.value(), cell.accessor());
if (cell.path() != null)
validateCellPath(cell.path());
}
}
private void validateCellPath(CellPath path)
{
if (!isComplex())
throw new MarshalException("Only complex cells should have a cell path");
assert type.isMultiCell();
if (type.isCollection())
((CollectionType)type).nameComparator().validate(path.get(0));
else
((UserType)type).nameComparator().validate(path.get(0));
}
public void appendCqlTo(CqlBuilder builder)
{
builder.append(name)
.append(' ')
.append(type);
if (isStatic())
builder.append(" static");
if (isMasked())View on GitHub (pinned to 88fd0f6a0e)