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

  1. 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.
  2. Ensure all writers use the same Jaeger schema version and 128-bit trace ID format before reading.
  3. Re-migrate the data with a conversion step that pads/normalizes IDs to 16 bytes if legacy 8-byte IDs must be kept.
  4. 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

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


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/74115f8757081c0f. Report an issue: GitHub.