spring-projects/spring-security · error · HttpMessageNotReadableException

An error occurred reading the OpenID Client Registration: ${

Error message

An error occurred reading the OpenID Client Registration: ${ex.getMessage()}

What it means

OidcClientRegistrationHttpMessageConverter.readInternal deserializes an HTTP request body into an OidcClientRegistration. Any exception raised while reading the JSON body or converting the parameter map (via the configured Converter<Map<String,Object>, OidcClientRegistration>) is wrapped into an HttpMessageNotReadableException with the message "An error occurred reading the OpenID Client Registration: <cause message>". This signals a malformed or semantically invalid client registration payload.

Source

Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/http/converter/OidcClientRegistrationHttpMessageConverter.java:93

		this.jsonMessageConverter = converter;
	}

	@Override
	protected boolean supports(Class<?> clazz) {
		return OidcClientRegistration.class.isAssignableFrom(clazz);
	}

	@Override
	@SuppressWarnings("unchecked")
	protected OidcClientRegistration readInternal(Class<? extends OidcClientRegistration> clazz,
			HttpInputMessage inputMessage) throws HttpMessageNotReadableException {
		try {
			Map<String, Object> clientRegistrationParameters = (Map<String, Object>) this.jsonMessageConverter
				.read(STRING_OBJECT_MAP.getType(), null, inputMessage);
			return this.clientRegistrationConverter.convert(clientRegistrationParameters);
		}
		catch (Exception ex) {
			throw new HttpMessageNotReadableException(
					"An error occurred reading the OpenID Client Registration: " + ex.getMessage(), ex, inputMessage);
		}
	}

	@Override
	protected void writeInternal(OidcClientRegistration clientRegistration, HttpOutputMessage outputMessage)
			throws HttpMessageNotWritableException {
		try {
			Map<String, Object> clientRegistrationParameters = this.clientRegistrationParametersConverter
				.convert(clientRegistration);
			this.jsonMessageConverter.write(clientRegistrationParameters, STRING_OBJECT_MAP.getType(),
					MediaType.APPLICATION_JSON, outputMessage);
		}
		catch (Exception ex) {
			throw new HttpMessageNotWritableException(
					"An error occurred writing the OpenID Client Registration: " + ex.getMessage(), ex);
		}
	}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Inspect the nested cause message to see the exact parse/convert failure and fix the request body accordingly.
  2. Ensure the request uses Content-Type: application/json and the body is a JSON object matching the OIDC Dynamic Client Registration schema.
  3. Validate required fields (client_name, redirect_uris for certain grant types, token_endpoint_auth_method) and allowed enum values before sending.
  4. If you need custom fields, register a custom Converter<Map<String,Object>, OidcClientRegistration> that accepts them instead of relying on the default.

Example fix

// before
POST /oauth2/register
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials

// after
POST /oauth2/register
Content-Type: application/json
{
  "client_name": "my-client",
  "grant_types": ["client_credentials"],
  "token_endpoint_auth_method": "client_secret_basic",
  "scope": "openid"
}
Defensive patterns

Strategy: validation

Validate before calling

boolean isValidRegistrationPayload(Map<String, Object> body) {
    return body != null
        && body.get("redirect_uris") instanceof List
        && body.get("grant_types") instanceof List
        && body.get("token_endpoint_auth_method") instanceof String;
}

Type guard

boolean isClientRegistrationBody(Object body) {
    return body instanceof Map<?, ?> m
        && m.get("client_name") instanceof String
        && m.get("redirect_uris") instanceof List<?>;
}

Try / catch

try {
    OidcClientRegistration reg = converter.read(OidcClientRegistration.class, inputMessage);
} catch (HttpMessageNotReadableException ex) {
    log.warn("Bad client registration payload: {}", ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage());
    response.sendError(HttpStatus.BAD_REQUEST.value());
}

Prevention

When it happens

Trigger: POSTing a client registration to the clientRegistrationEndpoint (or any endpoint using this converter) with a body that is not parseable JSON, not a JSON object, or that fails OidcClientRegistration validation — e.g. missing redirect_uris, invalid token_endpoint_auth_method value, or a field of the wrong JSON type.

Common situations: Sending form-encoded instead of JSON content-type; a typo like "redirect_uri" instead of "redirect_uris"; passing an array where an object is expected; invalid enum strings such as grant_type values; non-UTF8 bodies; ProGuard/serialization issues in test clients.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/46f811bbee067f26. Report an issue: GitHub.