spring-projects/spring-security · error · HttpMessageNotWritableException

An error occurred writing the OpenID Client Registration: ${

Error message

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

What it means

OidcClientRegistrationHttpMessageConverter.writeInternal serializes an OidcClientRegistration to the HTTP response. If converting the registration to a parameter map or writing it as JSON fails, the exception is wrapped in an HttpMessageNotWritableException with the message "An error occurred writing the OpenID Client Registration: <cause message>". It indicates the server could not render a client registration (typically the registration response) as JSON.

Source

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

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

	/**
	 * Sets the {@link Converter} used for converting the OpenID Client Registration
	 * parameters to an {@link OidcClientRegistration}.
	 * @param clientRegistrationConverter the {@link Converter} used for converting to an
	 * {@link OidcClientRegistration}
	 */
	public final void setClientRegistrationConverter(
			Converter<Map<String, Object>, OidcClientRegistration> clientRegistrationConverter) {
		Assert.notNull(clientRegistrationConverter, "clientRegistrationConverter cannot be null");
		this.clientRegistrationConverter = clientRegistrationConverter;
	}

	/**
	 * Sets the {@link Converter} used for converting the {@link OidcClientRegistration}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Check the nested cause to identify which conversion or serialization step failed.
  2. Ensure a functioning JSON HttpMessageConverter (e.g. MappingJackson2HttpMessageConverter) is on the classpath and registered on the endpoint.
  3. Review any custom clientRegistrationParametersConverter registered on OidcClientRegistrationHttpMessageConverter for bugs or incompatibility.
  4. Verify no earlier filter/interceptor has committed or closed the response output stream before the endpoint writes.

Example fix

// before (custom converter throws on null client_id issued value)
return Map.of("client_id", registration.getClientId(), "redirect_uris", registration.getRedirectUris());

// after (handle absent values and only include set fields)
Map<String, Object> params = new HashMap<>();
params.put("client_id", registration.getClientId());
if (!registration.getRedirectUris().isEmpty()) {
    params.put("redirect_uris", registration.getRedirectUris());
}
return params;
Defensive patterns

Strategy: try-catch

Validate before calling

boolean canSerialize(OidcClientRegistration reg) {
    return reg != null && reg.getClientId() != null;
}

Try / catch

try {
    converter.write(registration, MediaType.APPLICATION_JSON, outputMessage);
} catch (HttpMessageNotWritableException ex) {
    log.error("Failed to write client registration response: {}", ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage(), ex);
    response.sendError(HttpStatus.INTERNAL_SERVER_ERROR.value());
}

Prevention

When it happens

Trigger: The clientRegistrationEndpoint completes registration and writeInternal is invoked, but OidcClientRegistrationToParametersConverter or the underlying JSON message converter throws — e.g. a null/unset converter, a custom converter that throws, or a configured MappingJackson2HttpMessageConverter that cannot serialize a value in the registration.

Common situations: Spring MVC/Spring Security versions where the default JSON converter is unavailable or misconfigured; overriding the converter via HttpMessageConverters with one that rejects the output; a custom converter returning an incompatible map; response stream already committed/closed by a filter.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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