{"record":{"id":"bd4fa8747321aec1","repo":"karatelabs/karate","slug":"token-refresh-failed-expected-json-object-but-received","errorCode":null,"errorMessage":"Token refresh failed: expected JSON object but received ","messagePattern":"Token refresh failed: expected JSON object but received ","errorType":"exception","errorClass":"OAuth2Exception","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/http/OAuth2TokenManager.java","lineNumber":95,"sourceCode":"                throw new OAuth2Exception(errorMessage);\n            }\n\n            Json json;\n            try {\n                json = Json.of(body);\n            } catch (Exception e) {\n                String errorMessage = \"Token refresh failed: server returned invalid JSON response\";\n                logger.error(errorMessage);\n                currentToken = null;\n                throw new OAuth2Exception(errorMessage);\n            }\n\n            if (!json.isObject()) {\n                String errorMessage = \"Token refresh failed: expected JSON object but received \" +\n                    (json.isArray() ? \"array\" : \"primitive value\");\n                logger.error(errorMessage);\n                currentToken = null;\n                throw new OAuth2Exception(errorMessage);\n            }\n\n            Map<String, Object> data = json.asMap();\n            OAuth2Token newToken = OAuth2Token.fromMap(data);\n            storeToken(newToken);\n            logger.debug(\"Token refreshed successfully\");\n            return newToken;\n        } catch (OAuth2Exception e) {\n            throw e;\n        } catch (Exception e) {\n            String errorMessage = \"Token refresh failed: \" + e.getMessage();\n            logger.error(errorMessage);\n            currentToken = null;\n            throw new OAuth2Exception(errorMessage, e);\n        }\n    }\n\n    /**","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/http/OAuth2TokenManager.java#L77-L113","documentation":"After successfully parsing the refresh response, refreshToken() requires the JSON to be an object (a token payload with access_token etc.). If the body is a JSON array or primitive, it clears the cached token and throws OAuth2Exception identifying which non-object shape was received.","triggerScenarios":"Token endpoint responds with `[...]` or `\"string\"`/`123` — e.g. an introspection endpoint returning an array, or a misconfigured URL returning a JSON list of endpoints.","commonSituations":"Pointing the manager at an OIDC discovery document or JWKS (JSON object confusion aside) or other array-returning endpoint; custom idps returning wrapped payloads.","solutions":["Confirm the URL is the token endpoint (RFC 6749) which returns a flat JSON object.","Unwrap envelope responses before token management, or use a custom token response handler.","Compare received shape (message says array vs primitive) against expected `{access_token, ...}`.","Test the endpoint with curl to see the actual JSON body.­"],"exampleFix":"// before\n// tokenUrl points at /.well-known/openid-configuration returning object of URLs — wrong shape elsewhere\n// after\n// tokenUrl = \"https://idp.example.com/oauth2/token\" returning {\"access_token\":\"...\",\"token_type\":\"Bearer\"}","handlingStrategy":"try-catch","validationCode":"// sanity-check endpoint shape once at startup\nvar body = JSON.parse(httpGet(tokenUrl).body); if (Array.isArray(body)) throw new Error('tokenUrl returns an array, not an object');","typeGuard":null,"tryCatchPattern":"try { token = mgr.refresh(); } catch (OAuth2Exception e) { if (e.getMessage().contains('expected JSON object')) { log.error('Wrong endpoint or enveloped response: ' + e.getMessage()); fixEndpointOrUnwrap(); } else throw e; }","preventionTips":["Use the token endpoint, not discovery/JWKS/introspection URLs","Ensure the response is a flat object {access_token, ...}","Curl the endpoint to confirm the JSON shape before configuring","Unwrap envelope-style responses at a lower layer if your IdP wraps payloads"],"tags":["oauth2","token-refresh","unexpected-response-shape"],"backgroundTag":"unexpected-response-shape","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"}