JuliusBrussee/caveman · error
langfuse decode: %w
Error message
langfuse decode: %w
What it means
decodeLangfuse tries a langfuseEnvelope with an Observations array first, then a bare []langfuseObservation; if the bare-array unmarshal also fails, its json error is wrapped as 'langfuse decode: %w'. The wrapped message distinguishes shape problems ('invalid character ...') from field-type mismatches on a specific observation property.
Source
Thrown at shared/platform/importers/langfuse.go:63
obs, err := decodeLangfuse(data)
if err != nil {
return nil, err
}
rows := make([]Span, 0, len(obs))
for _, o := range obs {
rows = append(rows, mapLangfuse(o, opts))
}
return rows, nil
}
func decodeLangfuse(data []byte) ([]langfuseObservation, error) {
var env langfuseEnvelope
if err := json.Unmarshal(data, &env); err == nil && env.Observations != nil {
return env.Observations, nil
}
var arr []langfuseObservation
if err := json.Unmarshal(data, &arr); err != nil {
return nil, fmt.Errorf("langfuse decode: %w", err)
}
return arr, nil
}
func mapLangfuse(o langfuseObservation, opts Options) Span {
start, startNs := parseTimeFlexible(o.StartTime)
end, endNs := parseTimeFlexible(o.EndTime)
status := "ok"
switch o.Level {
case "ERROR":
status = "error"
case "WARNING":
status = "unset"
}
spanType := o.Type
if spanType == "" {View on GitHub (pinned to 27d5a3981a)
Solutions
- Check the wrapped json error to see if the top-level shape or a typed field failed
- Ensure input is an observations export: {"observations":[...]} or a bare array of observation objects
- If the field type changed upstream, coerce it to the expected type in pre-processing
- Confirm the saved file is complete JSON, not a truncated or multi-document stream
Example fix
// before
raw := []byte(`{"traces":[{"id":"t1"}]}`) // wrong export
rows, sum, err := importers.Import(importers.FormatLangfuse, raw, opts)
// after
raw := []byte(`{"observations":[{"id":"o1","startTime":"2026-01-01T00:00:00Z"}]}`)
rows, sum, err := importers.Import(importers.FormatLangfuse, raw, opts) Defensive patterns
Strategy: validation
Validate before calling
func looksLikeLangfuse(data []byte) bool {
d := bytes.TrimSpace(data)
return len(d) > 0 && (d[0] == '[' || bytes.Contains(d, []byte("\"observations\"")))
} Try / catch
if _, _, err := importers.Import(importers.FormatLangfuse, raw, opts); err != nil { if strings.Contains(err.Error(), "langfuse decode") { return fmt.Errorf("not a Langfuse observations export: %w", err) } } Prevention
- Download the observations export, not traces, when using this format
- Automate Langfuse export fetching to avoid wrong-artifact mistakes
- Validate the file contains "observations":[ before import
When it happens
Trigger: Passing the Langfuse traces export instead of the observations export (different schema); an object wrapper keyed differently than "observations"; an observation whose typed field (e.g. latencyNumbers) holds the wrong JSON type; empty or truncated input.
Common situations: Downloading the wrong export artifact from Langfuse UI (traces vs observations); API response shape change between Langfuse versions; saving an error body from a rate-limited request; concatenating NDJSON pages.
Related errors
- generic decode: expected a JSON array or {"data":[...]} of o
- helicone decode: %w
- otlp decode: %w
- corpus provider conversion supports string or null content
- cachebench: verifier returned duplicate or invalid JSON
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/c482b2e634e63fde.
Report an issue: GitHub.