jaegertracing/jaeger · error
TraceID is not a 128bit integer
Error message
TraceID is not a 128bit integer
What it means
ErrTraceIDWrongLength is returned by TraceID.UnmarshalCQL in dbmodel/cql_udt.go when the byte slice Cassandra holds for a trace_id is not exactly 16 bytes (128 bits). Jaeger trace IDs are fixed-size [16]byte values; anything else in the column means the data was written by an incompatible writer or corrupted. MarshalCQL always writes the full 16 bytes, so the error surfaces on read/unmarshal.
Source
Thrown at internal/storage/v1/cassandra/spanstore/dbmodel/cql_udt.go:15
// Copyright (c) 2019 The Jaeger Authors.
// Copyright (c) 2017 Uber Technologies, Inc.
// SPDX-License-Identifier: Apache-2.0
package dbmodel
import (
"errors"
"fmt"
gocql "github.com/apache/cassandra-gocql-driver/v2"
)
// ErrTraceIDWrongLength is an error that occurs when cassandra has a TraceID that's not 128 bits long
var ErrTraceIDWrongLength = errors.New("TraceID is not a 128bit integer")
// MarshalCQL handles marshaling DBTraceID (e.g. in SpanRef)
func (t TraceID) MarshalCQL(gocql.TypeInfo) ([]byte, error) {
return t[:], nil
}
// UnmarshalCQL handles unmarshaling DBTraceID (e.g. in SpanRef)
func (t *TraceID) UnmarshalCQL(_ gocql.TypeInfo, data []byte) error {
if len(data) != 16 {
return ErrTraceIDWrongLength
}
copy(t[:], data)
return nil
}
// MarshalUDT handles marshalling a Tag.
func (t *KeyValue) MarshalUDT(name string, info gocql.TypeInfo) ([]byte, error) {
switch name {View on GitHub (pinned to 806f444784)
Solutions
- Identify the offending rows (e.g. SELECT trace_id WHERE length mismatch) and fix or remove data that was not written as 16-byte IDs.
- Ensure all writers use the same Jaeger schema version and 128-bit trace ID format before reading.
- Re-migrate the data with a conversion step that pads/normalizes IDs to 16 bytes if legacy 8-byte IDs must be kept.
- In application code, validate trace IDs at ingestion time so short IDs never reach storage.
Example fix
// before
id, _ := model.TraceIDFromString("abc123") // may produce non-128-bit id stored elsewhere
// after
if len(idBytes) != 16 { /* normalize or reject before writing */ } Defensive patterns
Strategy: validation
Validate before calling
if len(traceIDBytes) != 16 {
return fmt.Errorf("trace ID must be 16 bytes, got %d", len(traceIDBytes))
} Type guard
func isValidTraceID(b []byte) bool { return len(b) == 16 } Try / catch
if err := row.Scan(&dbTraceID); err != nil {
if errors.Is(err, dbmodel.ErrTraceIDWrongLength) {
log.Warn("skipping row with corrupt trace_id"); continue
}
return err
} Prevention
- Validate trace ID length (16 bytes) at ingestion, before writing to Cassandra.
- Never hand-edit or truncate trace_id columns; use the Jaeger schema and writer only.
- Check for ErrTraceIDWrongLength with errors.Is when scanning legacy data.
When it happens
Trigger: UnmarshalCQL receives a byte slice whose length is not 16 while the gocql driver scans a trace_id column — e.g. rows written to the traces/spans table by an older schema or external tool storing shorter (32-bit/64-bit style) IDs, or malformed UDT data.
Common situations: Reading a Cassandra database populated by a different tracing backend or an outdated Jaeger schema; manual data migration copying truncated IDs; corrupt rows after partial migrations; tests like TestDBModelUDTMarshall that feed wrong-length bytes.
Related errors
- invalid TraceID length: %d
- invalid length %d of decoded trace ID %q, expected %d bytes
- failed to decode trace ID: %w
- trace_ttl can either be 0 or greater than or equal to 1 seco
- dependencies_ttl can either be 0 or greater than or equal to
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/74115f8757081c0f.
Report an issue: GitHub.