jaegertracing/jaeger · error
unknown column for position: %q
Error message
unknown column for position: %q
What it means
KeyValue.MarshalUDT implements gocql's UDTMarshaller; Cassandra sends the UDT field names for the tag UDT and each must match a known column (tag_key, tag_type, value_string, value_bool, value_int64, value_double, value_binary). Any other name means the Cassandra-side UDT schema drifted from this Go struct. This is a schema-contract mismatch, not a data problem.
Source
Thrown at internal/storage/v1/cassandra/spanstore/dbmodel/cql_udt.go:49
// MarshalUDT handles marshalling a Tag.
func (t *KeyValue) MarshalUDT(name string, info gocql.TypeInfo) ([]byte, error) {
switch name {
case "key":
return gocql.Marshal(info, t.Key)
case "value_type":
return gocql.Marshal(info, t.ValueType)
case "value_string":
return gocql.Marshal(info, t.ValueString)
case "value_bool":
return gocql.Marshal(info, t.ValueBool)
case "value_long":
return gocql.Marshal(info, t.ValueInt64)
case "value_double":
return gocql.Marshal(info, t.ValueFloat64)
case "value_binary":
return gocql.Marshal(info, t.ValueBinary)
default:
return nil, fmt.Errorf("unknown column for position: %q", name)
}
}
// UnmarshalUDT handles unmarshalling a Tag.
func (t *KeyValue) UnmarshalUDT(name string, info gocql.TypeInfo, data []byte) error {
switch name {
case "key":
return gocql.Unmarshal(info, data, &t.Key)
case "value_type":
return gocql.Unmarshal(info, data, &t.ValueType)
case "value_string":
return gocql.Unmarshal(info, data, &t.ValueString)
case "value_bool":
return gocql.Unmarshal(info, data, &t.ValueBool)
case "value_long":
return gocql.Unmarshal(info, data, &t.ValueInt64)
case "value_double":
return gocql.Unmarshal(info, data, &t.ValueFloat64)View on GitHub (pinned to 806f444784)
Solutions
- Compare the tags UDT definition (DESCRIBE keyspace / system_schema.usertypes) against the case names in cql_udt.go and re-apply the canonical Jaeger schema (migrations from plugin/storage/cassandra).
- Remove or rename any custom/stray columns added to the UDT; Cassandra UDTs cannot DROP fields, so recreate the UDT/table if drifted.
- Ensure the Jaeger binary and the schema version were provisioned from the same release.
Example fix
// before (cqlsh, drifted UDT) ALTER TYPE tags ADD extra_field text; // after -- recreate UDT with exactly the fields dbmodel.KeyValue marshals: -- tag_key, tag_type, value_string, value_bool, value_int64, value_double, value_binary CREATE TYPE tags (...);
Defensive patterns
Strategy: validation
Validate before calling
// Run before deploying: compare UDT fields in Cassandra with expected ones
SELECT keyspace_name, type_name, field_names
FROM system_schema.usertypes
WHERE type_name IN ('tag','log','span_ref','process');
// tag must be exactly: tag_key, tag_type, value_string, value_bool, value_int64, value_double, value_binary Prevention
- Apply schema only through official Jaeger migrations, never ad-hoc ALTER TYPE.
- Validate UDT definitions against expected field names in CI after schema changes.
- Keep Jaeger binary and schema versions in lockstep.
- Avoid sharing one keyspace across different Jaeger versions.
When it happens
Trigger: Writing spans when the tags UDT in Cassandra contains a column not present in the dbmodel.KeyValue switch — e.g. a manually added column, a UDT created by a different Jaeger/schema version, or a typo'd column name in cqlsh DDL.
Common situations: Running a newer Jaeger against an old schema (or vice versa); custom ALTER TYPE additions to the UDT; restoring data into a keyspace whose UDTs were re-created with different field names.
Related errors
- error reading throughput from storage: %w
- error reading probabilities from storage: %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
- compaction_window should at least be 1 minute
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/2d72c3f6fa93e1b2.
Report an issue: GitHub.