{"record":{"id":"d29cca89257f1373","repo":"spring-projects/spring-security","slug":"an-error-occurred-reading-the-oauth-2-0-client-reg","errorCode":null,"errorMessage":"An error occurred reading the OAuth 2.0 Client Registration: + ex.getMessage()","messagePattern":"An error occurred reading the OAuth 2\\.0 Client Registration: \\+ ex\\.getMessage\\(\\)","errorType":"http","errorClass":"HttpMessageNotReadableException","httpStatus":400,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/http/converter/OAuth2ClientRegistrationHttpMessageConverter.java","lineNumber":93,"sourceCode":"\t\tthis.jsonMessageConverter = converter;\n\t}\n\n\t@Override\n\tprotected boolean supports(Class<?> clazz) {\n\t\treturn OAuth2ClientRegistration.class.isAssignableFrom(clazz);\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tprotected OAuth2ClientRegistration readInternal(Class<? extends OAuth2ClientRegistration> clazz,\n\t\t\tHttpInputMessage inputMessage) throws HttpMessageNotReadableException {\n\t\ttry {\n\t\t\tMap<String, Object> clientRegistrationParameters = (Map<String, Object>) this.jsonMessageConverter\n\t\t\t\t.read(STRING_OBJECT_MAP.getType(), null, inputMessage);\n\t\t\treturn this.clientRegistrationConverter.convert(clientRegistrationParameters);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new HttpMessageNotReadableException(\n\t\t\t\t\t\"An error occurred reading the OAuth 2.0 Client Registration: \" + ex.getMessage(), ex,\n\t\t\t\t\tinputMessage);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void writeInternal(OAuth2ClientRegistration clientRegistration, HttpOutputMessage outputMessage)\n\t\t\tthrows HttpMessageNotWritableException {\n\t\ttry {\n\t\t\tMap<String, Object> clientRegistrationParameters = this.clientRegistrationParametersConverter\n\t\t\t\t.convert(clientRegistration);\n\t\t\tthis.jsonMessageConverter.write(clientRegistrationParameters, STRING_OBJECT_MAP.getType(),\n\t\t\t\t\tMediaType.APPLICATION_JSON, outputMessage);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new HttpMessageNotWritableException(\n\t\t\t\t\t\"An error occurred writing the OAuth 2.0 Client Registration: \" + ex.getMessage(), ex);\n\t\t}","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/http/converter/OAuth2ClientRegistrationHttpMessageConverter.java#L75-L111","documentation":"OAuth2ClientRegistrationHttpMessageConverter.readInternal wraps any exception raised while reading the request/response body as JSON and converting it to an OAuth2ClientRegistration. The JSON converter parses the Map<String,Object> and clientRegistrationConverter.convert() maps it to the typed object; any failure (malformed JSON, missing/invalid registration fields) is rethrown as org.springframework.http.converter.HttpMessageNotReadableException with the cause attached. This means the client registration document could not be read or validated.","triggerScenarios":"Calling OAuth2ClientRegistrationHttpMessageConverter.read() (via readInternal) when the body is not parseable JSON (syntax error, wrong Content-Type), the JSON converter throws, or the clientRegistration Converter.convert() throws because required fields (client_id, authorization/token/revocation endpoints, etc.) are missing or invalid.","commonSituations":"The authorization server / registration endpoint returns HTML or an empty/error body instead of JSON; Content-Type is not application/json so the JSON converter refuses to read; an OpenID Provider publishes an incomplete or non-conformant registration response (missing registration_client_uri fields); a custom clientRegistrationConverter is too strict about optional fields.","solutions":["Check the cause of the HttpMessageNotReadableException — if it is a JSON parse error the body is malformed; log the raw body to see what was actually returned.","Verify the response Content-Type is application/json and the endpoint actually returns a JSON registration document, not an HTML error page.","Validate the registration JSON against the OAuth2 client registration schema (required fields present) before/after conversion.","Ensure the JSON converter configured via setJsonMessageConverter supports the incoming MediaType.","Relax or correct a custom Converter registered with setClientRegistrationConverter if it rejects a valid registration."],"exampleFix":"// before\nResponseEntity<String> resp = rest.getForEntity(registrationUri, String.class);\nOAuth2ClientRegistration reg = converter.read(OAuth2ClientRegistration.class, new MockClientHttpResponse(resp.getBody(), resp.getHeaders())); // fails on HTML bodies\n// after\nif (!resp.getHeaders().getContentType().isCompatibleWith(MediaType.APPLICATION_JSON)) {\n  throw new IllegalStateException(\"Registration endpoint returned non-JSON: \" + resp.getBody());\n}\nOAuth2ClientRegistration reg = converter.read(OAuth2ClientRegistration.class, new MockClientHttpResponse(resp.getBody(), resp.getHeaders()));","handlingStrategy":"validation","validationCode":"// before reading\nif (body == null || body.isBlank()) throw new OAuth2IntrospectionException(\"empty registration body\");\nobjectMapper.readTree(body); // throws if malformed JSON\nif (!contentType.isCompatibleWith(MediaType.APPLICATION_JSON)) throw new IllegalArgumentException(\"non-JSON content type\");","typeGuard":null,"tryCatchPattern":"try {\n  return converter.read(OAuth2ClientRegistration.class, inputMessage);\n} catch (HttpMessageNotReadableException e) {\n  logger.warn(\"Invalid client registration response: {}\", e.getCause().toString());\n  throw new OAuth2ClientRegistrationException(\"Unreadable client registration\", e);\n}","preventionTips":["Always check HTTP status and Content-Type before passing a response to the converter.","Log raw response bodies on failure to diagnose non-JSON error pages.","Validate registration documents against the OAuth2/OIDC registration schema upstream.","Pin and test the JSON converter configuration used with the converter."],"tags":["spring-security","oauth2","http-message-converter","json-parse"],"backgroundTag":"invalid-json-response","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}