karatelabs/karate · error · OAuth2Exception

Missing 'client_id' in OAuth config

Error message

Missing 'client_id' in OAuth config

What it means

buildAuthorizationUrl() requires 'client_id' in the OAuth config to identify the application to the provider's authorize endpoint. When the key is missing, an OAuth2Exception is thrown right after the authorizationUrl check, with this exact message.

Solutions

  1. Add 'client_id' to the config map with the value from your provider app registration
  2. Verify the key is exactly 'client_id' (snake_case)
  3. Load and inspect the resolved config before starting the flow

Example fix

// before
config.put("clientId", "abc");
// after
config.put("client_id", "abc");
Defensive patterns

Strategy: validation

Validate before calling

Object clientId = config.get("client_id");
if (clientId == null || clientId.toString().isBlank()) {
    throw new IllegalArgumentException("config.client_id is required");
}

Type guard

static String requireConfigKey(Map<String, Object> config, String key) {
    Object v = config.get(key);
    if (!(v instanceof String s) || s.isBlank()) {
        throw new IllegalArgumentException("Missing '" + key + "' in OAuth config");
    }
    return s;
}

Try / catch

try {
    String url = handler.authUrl(pkce, redirectUri);
} catch (OAuth2Exception e) {
    if (e.getMessage().contains("client_id")) {
        throw new ConfigurationException("Add client_id to OAuth config", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: authUrl() invoked with a config map lacking 'client_id' — e.g. the secret was set but the ID was forgotten, the key was named 'clientId' instead of 'client_id', or the config loader skipped the field.

Common situations: Naming-convention mismatches (camelCase vs snake_case) after migrating config formats, incomplete app registration, or constructing config maps by hand.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/http/AuthorizationCodeAuthHandler.java:139

        } finally {
            if (callbackServer != null) {
                callbackServer.stop();
            }
        }
    }

    /**
     * Build authorization URL with all required parameters
     */
    private String buildAuthorizationUrl(PkceGenerator pkce, String redirectUri) {
        String authzEndpoint = (String) config.get("authorizationUrl");
        if (authzEndpoint == null) {
            throw new OAuth2Exception("Missing 'authorizationUrl' in OAuth config");
        }

        String clientId = (String) config.get("client_id");
        if (clientId == null) {
            throw new OAuth2Exception("Missing 'client_id' in OAuth config");
        }

        String scope = (String) config.getOrDefault("scope", "");

        StringBuilder url = new StringBuilder(authzEndpoint);
        url.append(authzEndpoint.contains("?") ? "&" : "?");
        url.append("response_type=code");
        url.append("&client_id=").append(urlEncode(clientId));
        url.append("&redirect_uri=").append(urlEncode(redirectUri));
        url.append("&code_challenge=").append(urlEncode(pkce.getChallenge()));
        url.append("&code_challenge_method=").append(pkce.getMethod());

        if (!scope.isEmpty()) {
            url.append("&scope=").append(urlEncode(scope));
        }

        // Add state for CSRF protection
        String state = generateState();

View on GitHub (pinned to a22eb90246)