{"record":{"id":"3401665c3a905686","repo":"larksuite/cli","slug":"app-registration-failed-http-d-response-not-js","errorCode":null,"errorMessage":"app registration failed: HTTP %d – response not JSON","messagePattern":"app registration failed: HTTP (.+?) – response not JSON","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/app_registration.go","lineNumber":128,"sourceCode":"\t\treturn nil, err\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\n\tresp, err := httpClient.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\tlogHTTPResponse(resp)\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"app registration failed: read body: %w\", err)\n\t}\n\n\tvar data map[string]interface{}\n\tif err := json.Unmarshal(body, &data); err != nil {\n\t\treturn nil, fmt.Errorf(\"app registration failed: HTTP %d – response not JSON\", resp.StatusCode)\n\t}\n\n\t_, hasError := data[\"error\"]\n\tif resp.StatusCode >= 400 || hasError {\n\t\tmsg := getStr(data, \"error_description\")\n\t\tif msg == \"\" {\n\t\t\tmsg = getStr(data, \"error\")\n\t\t}\n\t\tif msg == \"\" {\n\t\t\tmsg = \"Unknown error\"\n\t\t}\n\t\treturn nil, fmt.Errorf(\"app registration failed: %s\", msg)\n\t}\n\n\t// The protocol field is expire_in; accept the legacy expires_in spelling,\n\t// then normalize to protocol defaults.\n\texpiresIn := getInt(data, \"expire_in\", 0)\n\tif expiresIn <= 0 {","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/auth/app_registration.go#L110-L146","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"resp, err := http.Post(registrationEndpoint, \"application/x-www-form-urlencoded\", body)\nif err == nil {\n    ct := resp.Header.Get(\"Content-Type\")\n    if !strings.Contains(ct, \"application/json\") {\n        return fmt.Errorf(\"endpoint returned non-JSON content type %q (status %d)\", ct, resp.StatusCode)\n    }\n}","typeGuard":null,"tryCatchPattern":"resp, err := RequestAppRegistration(ctx, client, brand, errOut)\nif err != nil {\n    if strings.Contains(err.Error(), \"response not JSON\") {\n        // advise: check proxy/captive portal, retry on another network\n    }\n    return err\n}","preventionTips":["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."],"tags":["json","http","device-flow","network"],"backgroundTag":"non-json-response","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}