bytebase/bytebase · error
failed to read body of %s %s
Error message
failed to read body of %s %s
What it means
This error occurs when the DingTalk webhook provider fails to read the HTTP response body after a successful request dispatch (io.ReadAll on resp.Body returned an error). The provider wraps the underlying I/O error with the HTTP method and URL so you know which DingTalk API call failed. It indicates a connection was established and a response started, but the body transfer broke mid-stream.
Source
Thrown at backend/plugin/webhook/dingtalk/app.go:173
return nil, false, errors.Wrapf(err, "failed to construct %s %s", method, url)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
if strings.HasPrefix(url, "https://api.dingtalk.com") {
req.Header.Add("x-acs-dingtalk-access-token", p.token)
} else {
url = url + "?access_token=" + p.token
}
resp, err := p.c.Do(req)
if err != nil {
return nil, false, errors.Wrapf(err, "%s %s", method, url)
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err != nil {
return nil, false, errors.Wrapf(err, "failed to read body of %s %s", method, url)
}
var response struct {
Errcode int `json:"errcode"`
Errmsg string `json:"errmsg"`
Code string `json:"code"`
Message string `json:"message"`
}
if err := json.Unmarshal(b, &response); err != nil {
return nil, false, errors.Errorf("failed to unmarshal response")
}
if response.Errcode == 88 || response.Code == "InvalidAuthentication" {
if err := p.refreshToken(ctx); err != nil {
return nil, false, errors.Wrapf(err, "failed to refresh token")
}
return nil, true, nil
}View on GitHub (pinned to 1870550677)
Solutions
- Retry the request — the provider's do() loop handles token refresh retries but body-read errors fail immediately, so re-invoke the caller (e.g., re-run the webhook send).
- Check network path to DingTalk: verify no proxy/firewall is truncating responses to oapi.dingtalk.com / api.dingtalk.com (curl the endpoint from the host).
- Increase the http.Client timeout or configure a transport with sane idle-connection timeouts if a custom client was injected.
- Inspect the wrapped underlying error (errors.Cause) to distinguish reset, timeout, or TLS failure and address accordingly.
Example fix
// before: single-shot call
b, err := p.do(ctx, http.MethodPost, url, payload)
if err != nil { return err }
// after: retry transient body-read failures
var b []byte
for i := 0; i < 3; i++ {
b, err = p.do(ctx, http.MethodPost, url, payload)
if err == nil { break }
if !isTransientNetErr(errors.Cause(err)) { return err }
time.Sleep(time.Duration(i+1) * time.Second)
} Defensive patterns
Strategy: retry
Try / catch
var b []byte
for i := 0; i < 3; i++ {
b, err = p.do(ctx, http.MethodPost, url, payload)
if err == nil { break }
if !isTransient(errors.Cause(err)) { return err }
select {
case <-ctx.Done(): return ctx.Err()
case <-time.After(backoff(i)):
}
} Prevention
- Deploy in a network with stable egress to api.dingtalk.com and oapi.dingtalk.com.
- Set sensible http.Client/transport timeouts instead of unlimited waits.
- Wrap webhook sends with an application-level retry with exponential backoff.
- Monitor for transient network errors in logs and alert on sustained rates.
When it happens
Trigger: Any call to provider.do() (used by getIDByPhone, sendMessage, getIDByEmail, getUserIDByEmail) where the response from https://oapi.dingtalk.com or https://api.dingtalk.com is truncated: connection reset by server, read timeout mid-body, proxy closing the connection, or TLS termination failure during body transfer.
Common situations: Corporate proxies or firewalls that kill long-running responses; network flakiness in containers/Kubernetes with aggressive connection idle timeouts; DingTalk API returning a chunked response that is interrupted; DNS-level hijacking devices that reset connections.
Related errors
- read body of POST %s
- failed to read response body
- failed to read %s response body: %s
- failed to read response body
- POST %s
AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06).
Data as JSON: /api/errors/ac246218d3dea4ca.
Report an issue: GitHub.