{"record":{"id":"6ad7b31dbc90fa09","repo":"karatelabs/karate","slug":"missing-client-id-in-oauth-config","errorCode":null,"errorMessage":"Missing 'client_id' in OAuth config","messagePattern":"Missing 'client_id' in OAuth config","errorType":"validation","errorClass":"OAuth2Exception","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/http/AuthorizationCodeAuthHandler.java","lineNumber":139,"sourceCode":"        } finally {\n            if (callbackServer != null) {\n                callbackServer.stop();\n            }\n        }\n    }\n\n    /**\n     * Build authorization URL with all required parameters\n     */\n    private String buildAuthorizationUrl(PkceGenerator pkce, String redirectUri) {\n        String authzEndpoint = (String) config.get(\"authorizationUrl\");\n        if (authzEndpoint == null) {\n            throw new OAuth2Exception(\"Missing 'authorizationUrl' in OAuth config\");\n        }\n\n        String clientId = (String) config.get(\"client_id\");\n        if (clientId == null) {\n            throw new OAuth2Exception(\"Missing 'client_id' in OAuth config\");\n        }\n\n        String scope = (String) config.getOrDefault(\"scope\", \"\");\n\n        StringBuilder url = new StringBuilder(authzEndpoint);\n        url.append(authzEndpoint.contains(\"?\") ? \"&\" : \"?\");\n        url.append(\"response_type=code\");\n        url.append(\"&client_id=\").append(urlEncode(clientId));\n        url.append(\"&redirect_uri=\").append(urlEncode(redirectUri));\n        url.append(\"&code_challenge=\").append(urlEncode(pkce.getChallenge()));\n        url.append(\"&code_challenge_method=\").append(pkce.getMethod());\n\n        if (!scope.isEmpty()) {\n            url.append(\"&scope=\").append(urlEncode(scope));\n        }\n\n        // Add state for CSRF protection\n        String state = generateState();","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/http/AuthorizationCodeAuthHandler.java#L121-L157","documentation":"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.","triggerScenarios":"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.","commonSituations":"Naming-convention mismatches (camelCase vs snake_case) after migrating config formats, incomplete app registration, or constructing config maps by hand.","solutions":["Add 'client_id' to the config map with the value from your provider app registration","Verify the key is exactly 'client_id' (snake_case)","Load and inspect the resolved config before starting the flow"],"exampleFix":"// before\nconfig.put(\"clientId\", \"abc\");\n// after\nconfig.put(\"client_id\", \"abc\");","handlingStrategy":"validation","validationCode":"Object clientId = config.get(\"client_id\");\nif (clientId == null || clientId.toString().isBlank()) {\n    throw new IllegalArgumentException(\"config.client_id is required\");\n}","typeGuard":"static String requireConfigKey(Map<String, Object> config, String key) {\n    Object v = config.get(key);\n    if (!(v instanceof String s) || s.isBlank()) {\n        throw new IllegalArgumentException(\"Missing '\" + key + \"' in OAuth config\");\n    }\n    return s;\n}","tryCatchPattern":"try {\n    String url = handler.authUrl(pkce, redirectUri);\n} catch (OAuth2Exception e) {\n    if (e.getMessage().contains(\"client_id\")) {\n        throw new ConfigurationException(\"Add client_id to OAuth config\", e);\n    }\n    throw e;\n}","preventionTips":["Use snake_case keys exactly as the handler expects (client_id, not clientId)","Validate all required keys together before starting the flow","Centralize config loading so required-field checks happen once","Store credentials via env/secret manager and inject at load time with presence checks"],"tags":["oauth2","configuration","missing-config","authentication"],"backgroundTag":"missing-required-config-field","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"}