jaegertracing/jaeger · error

cannot copy stored trace: %w

Error message

cannot copy stored trace: %w

What it means

memory store's cloneTrace deep-copies a stored trace by marshal/unmarshal round-trip. If marshaling the source traces fails, it returns this error so callers never get a trace aliasing internal state — the memory store promises callers fully modifiable copies. pdata does not normally fail for well-formed traces, so this usually indicates corrupted internal state.

Source

Thrown at internal/storage/v2/memory/memory.go:189

// reader that modifies what it received would rewrite the stored trace for
// every later reader. Query-time adjusters do exactly that — the adjuster
// interface is documented as modifying a trace in place — as does any
// query-interceptor extension that redacts attributes on the return path.
//
// This restores for the v2 store the guarantee #2720 added to the v1 store,
// which was lost when the v1 implementation was deleted in #7711, and it uses
// the same mechanism. A proto round-trip is the only copy that is deep for every
// field: ptrace.Traces.CopyTo looks like the cheaper equivalent, but it assigns
// bytes-valued attributes by slice (`ov.BytesValue = t.BytesValue` in pdata's
// generated CopyAnyValue), leaving the clone sharing a backing array with the
// store, which a reader can then rewrite through pcommon.ByteSlice.SetAt.
// Nested array and kvlist values are copied properly, so bytes are the only
// gap — but relying on that is how this class of bug survives, and the contract
// this upholds promises callers a trace they may modify however they like.
func cloneTrace(src ptrace.Traces) (ptrace.Traces, error) {
	buf, err := marshalTraces(src)
	if err != nil {
		return ptrace.Traces{}, fmt.Errorf("cannot copy stored trace: %w", err)
	}
	dst, err := unmarshalTraces(buf)
	if err != nil {
		return ptrace.Traces{}, fmt.Errorf("cannot copy stored trace: %w", err)
	}
	return dst, nil
}

// Indirected so that tests can exercise cloneTrace's error paths, which pdata
// does not produce for a well-formed trace held by the store.
var (
	marshalTraces   = new(ptrace.ProtoMarshaler).MarshalTraces
	unmarshalTraces = new(ptrace.ProtoUnmarshaler).UnmarshalTraces
)

func (st *Store) GetDependencies(ctx context.Context, query depstore.QueryParameters) ([]model.DependencyLink, error) {
	m := st.getTenant(tenancy.GetTenant(ctx))
	return m.getDependencies(query)

View on GitHub (pinned to 806f444784)

Solutions

  1. Report/investigate the underlying marshal error — the stored trace is malformed
  2. Re-ingest or evict the affected trace from the store
  3. Check jaeger/pdata version compatibility if traces came from deserialization
Defensive patterns

Strategy: try-catch

Try / catch

clone, err := cloneTrace(src)
if err != nil {
    // stored trace is unusable: log wrapped cause, skip or evict trace
    return fmt.Errorf("skipping corrupt trace: %w", err)
}

Prevention

When it happens

Trigger: Calling cloneTrace (via the memory store's read/copy paths) when marshalTraces(src) returns an error, e.g. corrupt pdata held in the store.

Common situations: Rare in practice; indicates a bug or corrupted in-memory trace data; surfaced in tests via the indirection hooks of marshalTraces/unmarshalTraces.

Related errors


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