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

  1. Check the HTTP status in the message: 5xx/502 means server/gateway trouble — retry later.
  2. Curl the registration endpoint from the same machine to see the raw body being returned.
  3. Disable VPN/proxy or captive-portal interference, or switch networks.
  4. Clear any TLS-inspecting middleboxes that rewrite responses; verify the endpoint serves application/json.
  5. 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

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


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