JuliusBrussee/caveman · error
mapped span_id is empty
Error message
mapped span_id is empty
What it means
Same final validation as 1183 but for SpanID: the mapped span_id path resolved, yet the resulting string is empty after trimming. Every span needs a non-empty span ID because it is the primary identifier in caveman.spans. The check runs after trace_id, so trace ID was valid on this record.
Source
Thrown at shared/platform/importers/generic.go:162
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":
sp.TraceID = v
case "span_id":
sp.SpanID = vView on GitHub (pinned to 27d5a3981a)
Solutions
- Inspect the failing record and populate or drop it upstream
- Re-point the span_id mapping at the field that actually holds a non-empty value on every record
- Synthesize span IDs during pre-processing if the source genuinely lacks them
- Verify the mapping is not pointing at trace_id's field on records where both coincide
Example fix
// before
rec := map[string]any{"traceId": "t1", "spanId": nil, "started_at": "2026-01-01T00:00:00Z"}
// after
rec := map[string]any{"traceId": "t1", "spanId": "s1", "started_at": "2026-01-01T00:00:00Z"} Defensive patterns
Strategy: validation
Validate before calling
func hasNonEmptySpanID(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(), "span_id is empty") { /* drop or generate span ID for that record */ } Prevention
- Filter records with blank span IDs before import
- Generate span IDs (UUID) in pre-processing when the source omits them
- Assert non-empty span IDs in the exporting system's schema
When it happens
Trigger: Record has span_id present but empty/null/whitespace; span ID stored under a different populated field while the mapped one is a placeholder; asString of a non-string value (object, array) yielding an empty result.
Common situations: Exports where parent-only or synthetic rows carry an empty span ID; partial renames in the source schema leaving the old key present but blank; mapping span_id to a field that only exists on child spans.
Related errors
- mapped trace_id is empty
- generic import requires a %q mapping
- generic decode: expected a JSON array or {"data":[...]} of o
- mapped source path %q for required target %q was not found
- mapped timestamp is missing or invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/4315e8062f2240b8.
Report an issue: GitHub.