JuliusBrussee/caveman · error
helicone decode: %w
Error message
helicone decode: %w
What it means
decodeHelicone tries two shapes: a heliconeEnvelope object with a Data array, then a bare array of heliconeRecords. When both json.Unmarshal attempts fail, the second (bare-array) error is wrapped as 'helicone decode: %w'. The wrapped error is Go's encoding/json detail (e.g. 'invalid character ... looking for beginning of value' or a type mismatch on a record field).
Source
Thrown at shared/platform/importers/helicone.go:67
recs, err := decodeHelicone(data)
if err != nil {
return nil, err
}
rows := make([]Span, 0, len(recs))
for _, rec := range recs {
rows = append(rows, mapHelicone(rec, opts))
}
return rows, nil
}
func decodeHelicone(data []byte) ([]heliconeRecord, error) {
var env heliconeEnvelope
if err := json.Unmarshal(data, &env); err == nil && env.Data != nil {
return env.Data, nil
}
var arr []heliconeRecord
if err := json.Unmarshal(data, &arr); err != nil {
return nil, fmt.Errorf("helicone decode: %w", err)
}
return arr, nil
}
func mapHelicone(rec heliconeRecord, opts Options) Span {
ts, _ := parseTimeFlexible(rec.CreatedAt)
model := rec.Response.Model
if model == "" {
model = rec.Request.Model
}
provider := rec.Provider
if provider == "" {
provider = rec.Request.Provider
}
// 2xx is ok; anything else (including 0/unknown) is an error.
status := "ok"View on GitHub (pinned to 27d5a3981a)
Solutions
- Read the wrapped json error to identify whether the problem is overall shape or a specific field type
- Ensure input is one JSON document: either {"data":[...]} or a bare array of records
- If a record field changed type upstream, transform it to the expected type before import
- Verify the saved export is not an error payload or empty response
Example fix
// before
raw := []byte(`{"error":"unauthorized"}`)
rows, sum, err := importers.Import(importers.FormatHelicone, raw, opts)
// after
raw := []byte(`{"data":[{"id":"r1","created_at":"2026-01-01T00:00:00Z"}]}`)
rows, sum, err := importers.Import(importers.FormatHelicone, raw, opts) Defensive patterns
Strategy: validation
Validate before calling
func looksLikeHelicone(data []byte) bool {
d := bytes.TrimSpace(data)
return len(d) > 0 && (d[0] == '[' || bytes.Contains(d, []byte("\"data\"")))
} Try / catch
if _, _, err := importers.Import(importers.FormatHelicone, raw, opts); err != nil { if strings.Contains(err.Error(), "helicone decode") { return fmt.Errorf("not a Helicone export: %w", err) } } Prevention
- Save the raw API response from Helicone unchanged; do not concatenate pages
- Check the export contains "data":[ before importing
- Automate the export so manual copy/paste truncation cannot occur
When it happens
Trigger: Passing a bare JSON object that is neither shape; passing a JSONL stream; a record where a fixed-type field (e.g. numeric) holds a string, causing unmarshal to fail on []heliconeRecord; empty input bytes; truncated response body saved from a paged API call.
Common situations: Saving only the last page of a paginated Helicone export incorrectly; schema change in Helicone API responses changing a field's JSON type; concatenating multiple pages without wrapping them in an array; an auth-error JSON body {"error":...} saved instead of data.
Related errors
- generic decode: expected a JSON array or {"data":[...]} of o
- langfuse 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/d706ff080fd956c3.
Report an issue: GitHub.