{"record":{"id":"3456ce10d9525cf5","repo":"karatelabs/karate","slug":"token-endpoint-returned-invalid-response-truncate-bodystring","errorCode":null,"errorMessage":"Token endpoint returned invalid response: \" + truncate(bodyString)","messagePattern":"Token endpoint returned invalid response: \" \\+ truncate\\(bodyString\\)","errorType":"exception","errorClass":"OAuth2Exception","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/http/AuthorizationCodeAuthHandler.java","lineNumber":200,"sourceCode":"        builder.formField(\"redirect_uri\", redirectUri);\n        builder.formField(\"client_id\", config.get(\"client_id\"));\n        builder.formField(\"code_verifier\", codeVerifier);\n\n        // Optional client_secret (for confidential clients)\n        if (config.containsKey(\"client_secret\")) {\n            builder.formField(\"client_secret\", config.get(\"client_secret\"));\n        }\n\n        builder.header(\"Accept\", \"application/json\");\n\n        try {\n            HttpResponse response = builder.invoke(\"post\");\n            String bodyString = response.getBodyString();\n            Json json;\n            try {\n                json = Json.of(bodyString);\n            } catch (Exception e) {\n                throw new OAuth2Exception(\"Token endpoint returned invalid response: \" + truncate(bodyString));\n            }\n            if (!json.isObject()) {\n                throw new OAuth2Exception(\"Token endpoint returned unexpected response: \" + truncate(bodyString));\n            }\n            Map<String, Object> data = json.asMap();\n            if (data.containsKey(\"error\")) {\n                String error = String.valueOf(data.get(\"error\"));\n                String desc = data.containsKey(\"error_description\") ? String.valueOf(data.get(\"error_description\")) : null;\n                throw new OAuth2Exception(\"Token request failed: \" + error + (desc != null ? \" - \" + desc : \"\"));\n            }\n\n            logger.debug(\"Token exchange successful\");\n            return OAuth2Token.fromMap(data);\n\n        } catch (OAuth2Exception e) {\n            logger.error(\"Token exchange failed: {}\", e.getMessage());\n            throw new OAuth2Exception(\"Token exchange failed: \" + e.getMessage(), e);\n        } catch (Exception e) {","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/http/AuthorizationCodeAuthHandler.java#L182-L218","documentation":"Thrown by AuthorizationCodeAuthHandler.exchangeCodeForToken when the OAuth2 token endpoint's response body cannot be parsed as JSON at all (Json.of throws). The library requires a JSON body from the token endpoint per RFC 6749, so a non-JSON body (HTML error page, empty body, plain text) is treated as a fatal OAuth2 failure.","triggerScenarios":"The POST to the token endpoint (via builder.invoke(\"post\")) returned a body that is not valid JSON — e.g. an HTML gateway/proxy error page, an empty 200 response, a plain-text message, or a truncated response.","commonSituations":"Corporate proxy or API gateway intercepting the token request and returning an HTML error page; wrong tokenEndpointUri pointing at a login page; server returning 502/503 with a non-JSON body; network middleware stripping the body.","solutions":["Verify the tokenEndpointUri configuration points at the real token endpoint (usually ends in /token, not /authorize or a login page).","Check the actual HTTP status and raw body returned by the endpoint (curl the token endpoint or inspect logs) — an HTML body usually means a proxy/gateway error.","If behind a corporate proxy, configure proxy settings so the request reaches the OAuth provider directly.","Retry after confirming the provider's token endpoint is healthy; a transient gateway failure is a common cause."],"exampleFix":"// before\nOAuth2Config cfg = OAuth2Config.builder()\n    .tokenEndpointUri(\"https://provider.com/authorize\") // wrong endpoint\n    .build();\n// after\nOAuth2Config cfg = OAuth2Config.builder()\n    .tokenEndpointUri(\"https://provider.com/oauth2/token\") // JSON token endpoint\n    .build();","handlingStrategy":"try-catch","validationCode":"// Pre-check: token endpoint should be reachable and speak JSON\nString uri = cfg.getTokenEndpointUri();\nif (uri == null || !uri.startsWith(\"https://\") || uri.contains(\"authorize\")) {\n    throw new IllegalStateException(\"Suspect tokenEndpointUri: \" + uri);\n}","typeGuard":null,"tryCatchPattern":"try {\n    handler.token();\n} catch (OAuth2Exception e) {\n    if (e.getMessage().startsWith(\"Token endpoint returned invalid response\")) {\n        logger.error(\"Non-JSON token response; check endpoint/proxy: {}\", e.getMessage());\n        // inspect raw endpoint, fix tokenEndpointUri or proxy config\n    }\n}","preventionTips":["Point tokenEndpointUri at the /token endpoint, never /authorize or a login page.","Curl the token endpoint once to confirm it returns JSON.","Configure corporate proxy settings before running OAuth flows.","Alert on HTML/empty bodies from token endpoints in CI logs."],"tags":["oauth2","http","json","network"],"backgroundTag":"invalid-json-response","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}