{"record":{"id":"26d91add59db8ea3","repo":"spring-projects/spring-security","slug":"an-error-occurred-reading-the-oauth-2-0-device-aut","errorCode":null,"errorMessage":"An error occurred reading the OAuth 2.0 Device Authorization Response: ${ex.getMessage()}","messagePattern":"An error occurred reading the OAuth 2\\.0 Device Authorization Response: (.+?)","errorType":"http","errorClass":"HttpMessageNotReadableException","httpStatus":400,"severity":"error","filePath":"oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2DeviceAuthorizationResponseHttpMessageConverter.java","lineNumber":89,"sourceCode":"\t}\n\n\t@Override\n\tprotected boolean supports(Class<?> clazz) {\n\t\treturn OAuth2DeviceAuthorizationResponse.class.isAssignableFrom(clazz);\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tprotected OAuth2DeviceAuthorizationResponse readInternal(Class<? extends OAuth2DeviceAuthorizationResponse> clazz,\n\t\t\tHttpInputMessage inputMessage) throws HttpMessageNotReadableException {\n\n\t\ttry {\n\t\t\tMap<String, Object> deviceAuthorizationResponseParameters = (Map<String, Object>) this.jsonMessageConverter\n\t\t\t\t.read(STRING_OBJECT_MAP.getType(), null, inputMessage);\n\t\t\treturn this.deviceAuthorizationResponseConverter.convert(deviceAuthorizationResponseParameters);\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 Device Authorization Response: \" + ex.getMessage(), ex,\n\t\t\t\t\tinputMessage);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void writeInternal(OAuth2DeviceAuthorizationResponse deviceAuthorizationResponse,\n\t\t\tHttpOutputMessage outputMessage) throws HttpMessageNotWritableException {\n\n\t\ttry {\n\t\t\tMap<String, Object> deviceAuthorizationResponseParameters = this.deviceAuthorizationResponseParametersConverter\n\t\t\t\t.convert(deviceAuthorizationResponse);\n\t\t\tthis.jsonMessageConverter.write(deviceAuthorizationResponseParameters, 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 Device Authorization Response: \" + ex.getMessage(), ex);","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2DeviceAuthorizationResponseHttpMessageConverter.java#L71-L107","documentation":"This HttpMessageNotReadableException is thrown by OAuth2DeviceAuthorizationResponseHttpMessageConverter.readInternal when the JSON device authorization response from the authorization server cannot be converted into an OAuth2DeviceAuthorizationResponse. It wraps any exception (parse error, missing required parameters like device_code or verification_uri, type mismatches) produced by the JSON message converter or the parameter converter. The original cause message is appended for diagnosis.","triggerScenarios":"Calling readInternal/read on an OAuth2DeviceAuthorizationResponseHttpMessageConverter with a response body that is not valid JSON, is not a JSON object, or lacks required parameters (device_code, verification_uri) that OAuth2DeviceAuthorizationResponseParametersConverter requires.","commonSituations":"The device authorization endpoint returns an HTML error page instead of JSON (proxy, wrong URL), returns an error payload with HTTP 400 (e.g. authorization_pending is misused on this endpoint), or a custom message converter produces unexpected types.","solutions":["Log the wrapped cause (ex.getCause()) to see the actual conversion failure.","Verify the device authorization endpoint URL returns application/json per RFC 8628.","Check the response contains required parameters: device_code, verification_uri (and expires_in/user_code as configured).","Inspect for a proxy/gateway rewriting the response body (HTML error pages).","Set the converter's jsonMessageConverter (MappingJackson2HttpMessageConverter) so Jackson is on the classpath and configured."],"exampleFix":"// before\nOAuth2DeviceAuthorizationResponse response = converter.read(OAuth2DeviceAuthorizationResponse.class, inputMessage); // may throw\n// after\ntry {\n    OAuth2DeviceAuthorizationResponse response = converter.read(OAuth2DeviceAuthorizationResponse.class, inputMessage);\n} catch (HttpMessageNotReadableException ex) {\n    logger.error(\"Device authorization response read failed\", ex.getCause());\n    throw ex;\n}","handlingStrategy":"try-catch","validationCode":"if (!contentTypeCompatible(MediaType.APPLICATION_JSON)) {\n    throw new IllegalArgumentException(\"Device authorization response must be JSON\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    OAuth2DeviceAuthorizationResponse r = converter.read(OAuth2DeviceAuthorizationResponse.class, inputMessage);\n} catch (HttpMessageNotReadableException ex) {\n    logger.error(\"Device auth response unreadable\", ex.getCause());\n    throw new OAuth2AuthorizationException(new OAuth2Error(\"invalid_device_authorization_response\", ex.getMessage(), null), ex);\n}","preventionTips":["Assert the device authorization endpoint returns application/json before wiring it in.","Check required parameters (device_code, verification_uri) are present in a response contract test.","Keep Jackson on the classpath for the converter.","Watch for proxies returning HTML error pages in staging environments."],"tags":["oauth2","http-message-conversion","json","spring-security"],"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"}