karatelabs/karate · error · OAuth2Exception

Token refresh failed: expected JSON object but received

Error message

Token refresh failed: expected JSON object but received 

What it means

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.

Solutions

  1. Confirm the URL is the token endpoint (RFC 6749) which returns a flat JSON object.
  2. Unwrap envelope responses before token management, or use a custom token response handler.
  3. Compare received shape (message says array vs primitive) against expected `{access_token, ...}`.
  4. Test the endpoint with curl to see the actual JSON body.­

Example fix

// before
// tokenUrl points at /.well-known/openid-configuration returning object of URLs — wrong shape elsewhere
// after
// tokenUrl = "https://idp.example.com/oauth2/token" returning {"access_token":"...","token_type":"Bearer"}
Defensive patterns

Strategy: try-catch

Validate before calling

// sanity-check endpoint shape once at startup
var body = JSON.parse(httpGet(tokenUrl).body); if (Array.isArray(body)) throw new Error('tokenUrl returns an array, not an object');

Try / catch

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; }

Prevention

When it happens

Trigger: 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.

Common situations: Pointing the manager at an OIDC discovery document or JWKS (JSON object confusion aside) or other array-returning endpoint; custom idps returning wrapped payloads.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/bd4fa8747321aec1. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/http/OAuth2TokenManager.java:95

                throw new OAuth2Exception(errorMessage);
            }

            Json json;
            try {
                json = Json.of(body);
            } catch (Exception e) {
                String errorMessage = "Token refresh failed: server returned invalid JSON response";
                logger.error(errorMessage);
                currentToken = null;
                throw new OAuth2Exception(errorMessage);
            }

            if (!json.isObject()) {
                String errorMessage = "Token refresh failed: expected JSON object but received " +
                    (json.isArray() ? "array" : "primitive value");
                logger.error(errorMessage);
                currentToken = null;
                throw new OAuth2Exception(errorMessage);
            }

            Map<String, Object> data = json.asMap();
            OAuth2Token newToken = OAuth2Token.fromMap(data);
            storeToken(newToken);
            logger.debug("Token refreshed successfully");
            return newToken;
        } catch (OAuth2Exception e) {
            throw e;
        } catch (Exception e) {
            String errorMessage = "Token refresh failed: " + e.getMessage();
            logger.error(errorMessage);
            currentToken = null;
            throw new OAuth2Exception(errorMessage, e);
        }
    }

    /**

View on GitHub (pinned to a22eb90246)