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

  1. Ensure resp is non-nil and properly initialized before calling SerializeProtoResponse
  2. Check that all assigned enum values and oneof fields are valid for the proto definition
  3. Regenerate Go proto code if .pb.go files are out of sync with the .proto definitions
  4. 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

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


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)