spring-projects/spring-security · error · HttpMessageNotWritableException

An error occurred writing the OAuth 2.0 Authorization Server

Error message

An error occurred writing the OAuth 2.0 Authorization Server Metadata: + ex.getMessage()

What it means

OAuth2AuthorizationServerMetadataHttpMessageConverter.writeInternal wraps any exception raised while serializing OAuth2AuthorizationServerMetadata into a Map and writing it as JSON to the HTTP response. The converter catches Exception around the parameters conversion + jsonMessageConverter.write call and rethrows as org.springframework.http.converter.HttpMessageNotWritableException, preserving the cause (ex.getMessage() only appears in the message). This signals the authorization server metadata endpoint could not produce its JSON document.

Source

Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/http/converter/OAuth2AuthorizationServerMetadataHttpMessageConverter.java:100

		}
		catch (Exception ex) {
			throw new HttpMessageNotReadableException(
					"An error occurred reading the OAuth 2.0 Authorization Server Metadata: " + ex.getMessage(), ex,
					inputMessage);
		}
	}

	@Override
	protected void writeInternal(OAuth2AuthorizationServerMetadata authorizationServerMetadata,
			HttpOutputMessage outputMessage) throws HttpMessageNotWritableException {
		try {
			Map<String, Object> authorizationServerMetadataResponseParameters = this.authorizationServerMetadataParametersConverter
				.convert(authorizationServerMetadata);
			this.jsonMessageConverter.write(authorizationServerMetadataResponseParameters, STRING_OBJECT_MAP.getType(),
					MediaType.APPLICATION_JSON, outputMessage);
		}
		catch (Exception ex) {
			throw new HttpMessageNotWritableException(
					"An error occurred writing the OAuth 2.0 Authorization Server Metadata: " + ex.getMessage(), ex);
		}
	}

	/**
	 * Sets the {@link Converter} used for converting the OAuth 2.0 Authorization Server
	 * Metadata parameters to an {@link OAuth2AuthorizationServerMetadata}.
	 * @param authorizationServerMetadataConverter the {@link Converter} used for
	 * converting to an {@link OAuth2AuthorizationServerMetadata}.
	 */
	public final void setAuthorizationServerMetadataConverter(
			Converter<Map<String, Object>, OAuth2AuthorizationServerMetadata> authorizationServerMetadataConverter) {
		Assert.notNull(authorizationServerMetadataConverter, "authorizationServerMetadataConverter cannot be null");
		this.authorizationServerMetadataConverter = authorizationServerMetadataConverter;
	}

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

View on GitHub (pinned to 96852e8860)

Solutions

  1. Inspect the cause (ex.getCause()) logged with this message — it names the real failure (serialization error vs I/O error) and fix that root problem.
  2. Ensure a JSON-capable HttpMessageConverter (MappingJackson2HttpMessageConverter) with a working ObjectMapper is configured; check any custom converter set via setJsonMessageConverter.
  3. Validate the OAuth2AuthorizationServerMetadata (issuer URL well-formed, required fields present, custom parameters serializable) before it reaches the metadata endpoint.
  4. Review any custom Converter registered with setAuthorizationServerMetadataParametersConverter for thrown exceptions on your metadata instance.
  5. If caused by client disconnect / committed response, treat as benign infrastructure noise rather than a code bug.

Example fix

// before
@Bean
WebMvcConfigurer mvc() {
  return new WebMvcConfigurer() {
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
      converters.add(new StringHttpMessageConverter()); // no JSON converter -> write fails
    }
  };
}
// after
@Bean
WebMvcConfigurer mvc() {
  return new WebMvcConfigurer() {
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
      converters.add(new MappingJackson2HttpMessageConverter()); // JSON writer present
    }
  };
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before serving metadata
assert metadata != null && metadata.getIssuer() != null : "issuer required";
objectMapper.writeValueAsString(metadata.getParameters()); // throws early if unserializable

Try / catch

try {
  converter.write(metadata, MediaType.APPLICATION_JSON, outputMessage);
} catch (HttpMessageNotWritableException e) {
  logger.error("Failed to write authorization server metadata", e.getCause());
  response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}

Prevention

When it happens

Trigger: Calling OAuth2AuthorizationServerMetadataHttpMessageConverter.write() (via writeInternal) when the metadata-parameters Converter.convert() throws (invalid/null OAuth2AuthorizationServerMetadata fields) or when the underlying Jackson JSON converter fails to serialize the resulting Map<String,Object> to the HttpServletResponse output stream (I/O error, missing JSON converter, unserializable value).

Common situations: The configured ObjectMapper cannot serialize a custom metadata parameter added to the metadata object (e.g. a non-serializable object placed in the map); the servlet response was already committed or the client disconnected mid-write (broken pipe); someone replaced the default MappingJackson2HttpMessageConverter with a converter that cannot handle Map/JSON; a custom Converter supplied via setAuthorizationServerMetadataParametersConverter throws during convert().

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/a1bb5807aff87a29. Report an issue: GitHub.