geektutu/7days-golang · error

decoding response body: %v

Error message

decoding response body: %v

What it means

The day7 peer protocol encodes responses as protobuf; httpGetter.Get unmarshals the 200-response body into the out proto.Message with proto.Unmarshal. If the bytes are not a valid encoding of the expected message type, the failure is wrapped as "decoding response body: %v". This usually means the peer did not actually send a protobuf payload (wrong endpoint, wrong version, or a non-gee-cache server answering 200 with HTML/JSON).

Source

Thrown at gee-cache/day7-proto-buf/geecache/http.go:136

		url.QueryEscape(in.GetKey()),
	)
	res, err := http.Get(u)
	if err != nil {
		return err
	}
	defer res.Body.Close()

	if res.StatusCode != http.StatusOK {
		return fmt.Errorf("server returned: %v", res.Status)
	}

	bytes, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return fmt.Errorf("reading response body: %v", err)
	}

	if err = proto.Unmarshal(bytes, out); err != nil {
		return fmt.Errorf("decoding response body: %v", err)
	}

	return nil
}

var _ PeerGetter = (*httpGetter)(nil)

View on GitHub (pinned to cf36443821)

Solutions

  1. Confirm both sides of the peer connection use the same protobuf message schema (consistent-cache/v1) and day7 code
  2. Verify the peer URL/basePath resolves to the gee-cache handler, not another endpoint returning 200
  3. Upgrade/downgrade nodes so the entire ring speaks the same protocol
  4. Log a preview of the raw bytes on this error to identify what the peer actually sent

Example fix

// before
// client expects protobuf but peer serves plain bytes (day5 node in ring)
var out pb.Response
proto.Unmarshal(bytes, out) // decoding response body: unexpected wire type
// after
// keep ring membership homogeneous:
peers.Add("http://node1:8001", "http://node2:8001") // all day7, same .proto schema
Defensive patterns

Strategy: type-guard

Validate before calling

// cheap structural check before unmarshalling
if len(bytes) == 0 || bytes[0] > 20 { // protobuf fields start with small tags
    return fmt.Errorf("peer response is not protobuf (%q)", preview(bytes))
}

Type guard

func looksLikeProto(b []byte) bool {
    return len(b) > 0 && b[0] < 20 // plausible protobuf field header
}

Try / catch

err := g.Get(ctx, key, &out)
if err != nil {
    if strings.Contains(err.Error(), "decoding response body") {
        log.Printf("peer sent non-protobuf payload; check versions/basePath: %v", err)
        return g.getLocally(key) // degrade gracefully
    }
    return err
}

Prevention

When it happens

Trigger: Hitting a day5/day6 (plain text) peer from a day7 client; basePath pointing at the wrong service that returns 200 with non-protobuf data; corrupted/truncated body that still passed ReadAll; a proxy error page served with 200.

Common situations: Rolling upgrades with mixed versions in the hash ring; misconfigured basePath such as "/" hitting the app's HTML index; manually constructed test requests against the wrong handler.

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


AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03). Data as JSON: /api/errors/f8a6a8a8391fbbe4. Report an issue: GitHub.