larksuite/cli · error
app registration failed: HTTP %d – response not JSON
Error message
app registration failed: HTTP %d – response not JSON
What it means
Thrown by RequestAppRegistration at internal/auth/app_registration.go:128 when json.Unmarshal cannot decode the begin-endpoint response into a JSON object. The library reports the HTTP status because a non-JSON body almost always means an HTML error page, empty body, or gateway response instead of the device-flow payload. Note the raw JSON parse error is not included; only the status code is surfaced.
Source
Thrown at internal/auth/app_registration.go:128
return nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
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("app registration failed: read body: %w", err)
}
var data map[string]interface{}
if err := json.Unmarshal(body, &data); err != nil {
return nil, fmt.Errorf("app registration 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("app registration failed: %s", msg)
}
// The protocol field is expire_in; accept the legacy expires_in spelling,
// then normalize to protocol defaults.
expiresIn := getInt(data, "expire_in", 0)
if expiresIn <= 0 {View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Check the HTTP status in the message: 5xx/502 means server/gateway trouble — retry later.
- Curl the registration endpoint from the same machine to see the raw body being returned.
- Disable VPN/proxy or captive-portal interference, or switch networks.
- Clear any TLS-inspecting middleboxes that rewrite responses; verify the endpoint serves application/json.
- Report to the service owner if the server persistently returns non-JSON with status 200.
Defensive patterns
Strategy: fallback
Validate before calling
resp, err := http.Post(registrationEndpoint, "application/x-www-form-urlencoded", body)
if err == nil {
ct := resp.Header.Get("Content-Type")
if !strings.Contains(ct, "application/json") {
return fmt.Errorf("endpoint returned non-JSON content type %q (status %d)", ct, resp.StatusCode)
}
} Try / catch
resp, err := RequestAppRegistration(ctx, client, brand, errOut)
if err != nil {
if strings.Contains(err.Error(), "response not JSON") {
// advise: check proxy/captive portal, retry on another network
}
return err
} Prevention
- Verify no captive portal or MITM proxy rewrites responses (curl the endpoint first).
- Keep corporate TLS-inspection appliances from intercepting accounts.* hosts.
- Pin to networks with unrestricted egress to feishu.cn / larksuite.com.
When it happens
Trigger: The registration begin endpoint returns HTML (login/consent/captcha page), an empty body, a plaintext gateway error (502/504 from a reverse proxy), gzip/brotli content the client cannot auto-decode, or any non-JSON body for any HTTP status.
Common situations: Walled-garden/captive portal Wi-Fi returning an HTML interstitial; corporate proxy injecting a block page; regional network blocking accounts.feishu.cn/accounts.larksuite.com; CDN or WAF challenge pages; server outage returning an nginx error page.
Related errors
- poll parse error: %w
- Device authorization failed: read body: %v
- Device authorization failed: HTTP %d – response not JSON
- response parse error: %w (body: %s)
- parse response: %w
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/3401665c3a905686.
Report an issue: GitHub.