thanos-io/thanos · error
error marshaling proto response
Error message
error marshaling proto response: %v
What it means
SerializeProtoResponse marshals a protobuf response message to bytes before writing it to the HTTP response; if proto.Marshal fails, it writes a 500 to the client and returns this wrapped error. Marshal failures indicate the response message is invalid (e.g. required fields unset in older proto2 semantics, unknown enum values, or a nil/non-initializable message).
Solutions
- Ensure resp is non-nil and properly initialized before calling SerializeProtoResponse
- Check that all assigned enum values and oneof fields are valid for the proto definition
- Regenerate Go proto code if .pb.go files are out of sync with the .proto definitions
- Log the underlying error to identify which field/branch of the message is invalid
Example fix
// before
return util.SerializeProtoResponse(w, nil, compression)
// after
if resp == nil {
return errors.New("nil proto response")
}
return util.SerializeProtoResponse(w, resp, compression) Defensive patterns
Strategy: try-catch
Validate before calling
if resp == nil {
return errors.New("proto response is nil")
}
if _, err := proto.Marshal(resp); err != nil {
return fmt.Errorf("response not marshallable: %w", err)
} Type guard
func isMarshallable(m proto.Message) bool {
if m == nil { return false }
_, err := proto.Marshal(m)
return err == nil
} Try / catch
if err := util.SerializeProtoResponse(w, resp, compression); err != nil {
if strings.Contains(err.Error(), "error marshaling proto response") {
log.Errorf("bad response proto: %v", err)
http.Error(w, "internal serialization failure", http.StatusInternalServerError)
return
}
return err
} Prevention
- Always check for nil responses before serialization
- Regenerate proto code after schema changes
- Assign enum/oneof values only through generated setters
When it happens
Trigger: Calling SerializeProtoResponse with a resp message that proto.Marshal cannot serialize — typically a nil message, a message with invalid oneof/enum state, or corruption of the message structure.
Common situations: Handlers populating response protos incorrectly (wrong oneof branch, invalid enum number from manual field assignment), or passing nil after an upstream error path.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- error sending proto response
- Error decoding remote write request
- creating request to downstream URL
- error starting web server
- http.Error(w, err.Error(), http.StatusInternalServerError)
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/f51f5fd0ca4ac610.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cortex/util/http.go:257
return nil, nil
}
// tryBufferFromReader attempts to cast the reader to a `*bytes.Buffer` this is possible when using httpgrpc.
// If it fails it will return nil and false.
func tryBufferFromReader(reader io.Reader) (*bytes.Buffer, bool) {
if bufReader, ok := reader.(interface {
BytesBuffer() *bytes.Buffer
}); ok && bufReader != nil {
return bufReader.BytesBuffer(), true
}
return nil, false
}
// SerializeProtoResponse serializes a protobuf response into an HTTP response.
func SerializeProtoResponse(w http.ResponseWriter, resp proto.Message, compression CompressionType) error {
data, err := proto.Marshal(resp)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return fmt.Errorf("error marshaling proto response: %v", err)
}
switch compression {
case NoCompression:
case RawSnappy:
data = snappy.Encode(nil, data)
}
if _, err := w.Write(data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return fmt.Errorf("error sending proto response: %v", err)
}
return nil
}
View on GitHub (pinned to 35b8b99117)