thanos-io/thanos · error
unmarshal storepb.SeriesResponse frame for file
Error message
unmarshal storepb.SeriesResponse frame for file %s
What it means
NewLocalStoreFromJSONMmappableFile reads a file of newline-delimited storepb.SeriesResponse frames (grpcurl output) and unmarshals each frame with jsonpb; any decode failure is wrapped with the file path. It means one of the JSON frames does not match the storepb.SeriesResponse schema.
Solutions
- Regenerate the dump with the same Thanos proto version used to read it.
- Validate the offending line is valid JSON matching storepb.SeriesResponse (jq, protojson).
- Remove or fix the corrupted frame in the file.
- Ensure the file is a complete, non-truncated dump.
Example fix
// before grpcurl -plaintext store:10901 thanos.StoreInfo > dump.json # mixed responses // after grpcurl -plaintext -emit-defaults store:10901 thanos.Store/Series > series_frames.ndjson
Defensive patterns
Strategy: validation
Validate before calling
// validate each line before loading
for i, line := range lines {
var probe map[string]json.RawMessage
if json.Unmarshal([]byte(line), &probe) != nil || probe["series"] == nil {
return fmt.Errorf("frame %d not a SeriesResponse", i)
}
} Try / catch
if err != nil {
var perr *json.UnmarshalTypeError
if errors.As(err, &perr) { /* report offending line/field */ }
} Prevention
- Regenerate dumps whenever Thanos proto version changes
- Never hand-edit dumped frame files
- Verify dumps are fully flushed before use
When it happens
Trigger: Loading a cached/dumped store response file where a frame was truncated, written by an incompatible proto version, or is not a SeriesResponse JSON at all.
Common situations: Manually captured grpcurl output edited/corrupted; version mismatch between the tool that dumped the file and Thanos proto definitions; partially written file from an interrupted dump.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- empty exemplars data
- read meta
- failed to parse template
- failed to execute template
- failed to parse the template
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/4e5c1588c3c0bd97.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/store/local.go:86
c: f,
}
// Do quick pass for in-mem index.
content := f.Bytes()
contentStart := bytes.Index(content, []byte("{"))
if contentStart != -1 {
content = content[contentStart:]
}
if idx := bytes.LastIndex(content, []byte("}")); idx != -1 {
content = content[:idx+1]
}
skanner := NewNoCopyScanner(content, split)
resp := &storepb.SeriesResponse{}
for skanner.Scan() {
if err := jsonpb.Unmarshal(bytes.NewReader(skanner.Bytes()), resp); err != nil {
return nil, errors.Wrapf(err, "unmarshal storepb.SeriesResponse frame for file %s", path)
}
series := resp.GetSeries()
if series == nil {
level.Warn(logger).Log("msg", "not a valid series", "frame", resp.String())
continue
}
chks := make([]int, 0, len(series.Chunks))
// Sort chunks in separate slice by MinTime for easier lookup. Find global max and min.
for ci := range series.Chunks {
chks = append(chks, ci)
}
sort.Slice(chks, func(i, j int) bool {
return series.Chunks[chks[i]].MinTime < series.Chunks[chks[j]].MinTime
})
s.series = append(s.series, series)
s.sortedChunks = append(s.sortedChunks, chks)
}View on GitHub (pinned to 35b8b99117)