larksuite/cli · error

Device authorization failed: read body: %v

Error message

Device authorization failed: read body: %v

What it means

RequestDeviceAuthorization wraps an io.ReadAll failure while draining the device-authorization endpoint's HTTP response body. The HTTP request itself completed, but the response bytes could not be read (connection reset mid-body, timeout, truncated response). The %v verb embeds the underlying reader error without %w wrapping, so errors.Is/As cannot unwrap the cause.

Source

Thrown at internal/auth/device_flow.go:102

	form.Set("scope", scope)

	req, err := http.NewRequest("POST", endpoints.DeviceAuthorization, strings.NewReader(form.Encode()))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Authorization", "Basic "+basicAuth)

	resp, err := httpClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	logHTTPResponse(resp)

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("Device authorization failed: read body: %v", err)
	}

	var data map[string]interface{}
	if err := json.Unmarshal(body, &data); err != nil {
		return nil, fmt.Errorf("Device authorization failed: HTTP %d – response not JSON", resp.StatusCode)
	}

	_, hasError := data["error"]
	if resp.StatusCode >= 400 || hasError {
		msg := getStr(data, "error_description")
		if msg == "" {
			msg = getStr(data, "error")
		}
		if msg == "" {
			msg = "Unknown error"
		}
		return nil, fmt.Errorf("Device authorization failed: %s", msg)
	}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Retry RequestDeviceAuthorization — this is a transient transport-level read failure, not an auth rejection.
  2. Check network path to open.feishu.cn (proxy/VPN/firewall) and retry from a stable connection.
  3. If it recurs, capture the embedded error text after 'read body:' to identify the transport cause (reset, timeout, unexpected EOF).
  4. Consider replacing %v with %w when editing the code so callers can unwrap the cause.

Example fix

// before
return nil, fmt.Errorf("Device authorization failed: read body: %v", err)
// after
return nil, fmt.Errorf("Device authorization failed: read body: %w", err)
Defensive patterns

Strategy: retry

Try / catch

// retry up to 3 times on transient body-read failure
for i := 0; i < 3; i++ {
    resp, err := auth.RequestDeviceAuthorization(ctx, clientID, scopes)
    if err == nil { break }
    if strings.Contains(err.Error(), "read body:") && i < 2 { time.Sleep(backoff); continue }
    return err
}

Prevention

When it happens

Trigger: RequestDeviceAuthorization receives a 2xx/other response whose body read via io.ReadAll fails — server closes the connection mid-response, proxy truncates the transfer, or a network interruption occurs while streaming the body.

Common situations: Flaky corporate proxies or VPNs dropping keep-alive connections mid-body; Lark gateway timeouts on slow links; running the device flow behind an intercepting firewall that cuts large responses.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/8399d7f6c04579fa. Report an issue: GitHub.