JuliusBrussee/caveman · error

mapped trace_id is empty

Error message

mapped trace_id is empty

What it means

After mapping, mapGeneric verifies the resolved TraceID is non-empty after TrimSpace. This triggers when the source path WAS found but its value was empty, whitespace, or converted to an empty string by asString. It is distinct from error 1182 (path not found): here the path resolved but produced no usable identifier.

Source

Thrown at shared/platform/importers/generic.go:159

		case "string":
			assignString(&sp, target, asString(val))
		case "int":
			assignInt(&sp, target, parseFlexInt(val))
		case "float":
			sp.TotalCostUSD = roundUSD(parseFlexFloat(val))
		case "time":
			s, ns := parseTimeFlexible(val)
			if target == "timestamp" {
				sp.Timestamp = s
				startNs = ns
			} else {
				sp.EndTimestamp = s
				endNs = ns
			}
		}
	}
	if strings.TrimSpace(sp.TraceID) == "" {
		return Span{}, nil, fmt.Errorf("mapped trace_id is empty")
	}
	if strings.TrimSpace(sp.SpanID) == "" {
		return Span{}, nil, fmt.Errorf("mapped span_id is empty")
	}
	if sp.Timestamp == "" {
		return Span{}, nil, fmt.Errorf("mapped timestamp is missing or invalid")
	}
	if d := durationMS(startNs, endNs); d > 0 {
		sp.DurationMS = d
	}
	sp.Attributes = map[string]string{"import.source": "generic"}
	applyScope(&sp, opts)
	return sp, resolved, nil
}

func assignString(sp *Span, target, v string) {
	switch target {
	case "trace_id":

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Find the offending record (it is the one at the failing position) and either populate a real trace ID upstream or drop it
  2. If the field is sometimes empty, pre-process the data to synthesize a deterministic trace ID before import
  3. Double-check the mapping does not point at a sibling field that is frequently empty
  4. Treat empty trace/span IDs as data-quality defects at the source system, not importer configuration

Example fix

// before
rec := map[string]any{"traceId": "", "spanId": "s1", "started_at": "2026-01-01T00:00:00Z"}

// after
rec := map[string]any{"traceId": "gen-trace-1", "spanId": "s1", "started_at": "2026-01-01T00:00:00Z"}
Defensive patterns

Strategy: validation

Validate before calling

func hasNonEmptyTraceID(rec map[string]any, path string) bool {
	v, ok := lookupPath(rec, path)
	if !ok { return false }
	s, ok := v.(string)
	return ok && strings.TrimSpace(s) != ""
}

Type guard

func isUsableID(v any) bool {
	s, ok := v.(string)
	return ok && strings.TrimSpace(s) != ""
}

Try / catch

if strings.Contains(err.Error(), "trace_id is empty") { /* identify and drop/synthesize IDs for offending records */ }

Prevention

When it happens

Trigger: Records where the trace-id field exists but is "" or " "; a null JSON value that asString renders as empty; a numeric 0 or false in the trace-id field being stringified into something empty; mapping trace_id to a path that resolves to an object/array.

Common situations: Vendor exports that emit empty trace IDs for rootless/system spans; records from a pre-migration system that did not set trace IDs; mapping trace_id to the wrong field that is usually populated but empty on summary rows.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/1e991645c95678cd. Report an issue: GitHub.