{"record":{"id":"6318e00113bf8d5c","repo":"spring-projects/spring-security","slug":"registration-not-found","errorCode":null,"errorMessage":"registration not found","messagePattern":"registration not found","errorType":"exception","errorClass":"Saml2Exception","httpStatus":500,"severity":"error","filePath":"saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilter.java","lineNumber":172,"sourceCode":"\n\t\tprivate String metadataFilename = DEFAULT_METADATA_FILE_NAME;\n\n\t\tSaml2MetadataResponseResolverAdapter(RelyingPartyRegistrationResolver registrations,\n\t\t\t\tSaml2MetadataResolver metadataResolver) {\n\t\t\tthis.registrations = registrations;\n\t\t\tthis.metadataResolver = metadataResolver;\n\t\t}\n\n\t\t@Override\n\t\tpublic @Nullable Saml2MetadataResponse resolve(HttpServletRequest request) {\n\t\t\tRequestMatcher.MatchResult matcher = this.requestMatcher.matcher(request);\n\t\t\tif (!matcher.isMatch()) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tString registrationId = matcher.getVariables().get(\"registrationId\");\n\t\t\tRelyingPartyRegistration relyingPartyRegistration = this.registrations.resolve(request, registrationId);\n\t\t\tif (relyingPartyRegistration == null) {\n\t\t\t\tthrow new Saml2Exception(\"registration not found\");\n\t\t\t}\n\t\t\tregistrationId = relyingPartyRegistration.getRegistrationId();\n\t\t\tString metadata = this.metadataResolver.resolve(relyingPartyRegistration);\n\t\t\tString fileName = this.metadataFilename.replace(\"{registrationId}\", registrationId);\n\t\t\treturn new Saml2MetadataResponse(metadata, fileName);\n\t\t}\n\n\t\tvoid setRequestMatcher(RequestMatcher requestMatcher) {\n\t\t\tAssert.notNull(requestMatcher, \"requestMatcher cannot be null\");\n\t\t\tthis.requestMatcher = requestMatcher;\n\t\t}\n\n\t\tvoid setMetadataFilename(String metadataFilename) {\n\t\t\tAssert.hasText(metadataFilename, \"metadataFilename cannot be empty\");\n\t\t\tAssert.isTrue(metadataFilename.contains(\"{registrationId}\"),\n\t\t\t\t\t\"metadataFilename must contain a {registrationId} match variable\");\n\t\t\tthis.metadataFilename = metadataFilename;\n\t\t}","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilter.java#L154-L190","documentation":"Saml2MetadataFilter resolves the RelyingPartyRegistration for the {registrationId} path variable extracted from the request URI. When the underlying RelyingPartyRegistrationRepository has no registration with that id, resolve returns null and the filter throws this Saml2Exception instead of serving metadata.","triggerScenarios":"An HTTP GET hits the metadata endpoint (/saml2/metadata/{registrationId} or /saml2/metadata/{registrationId}/metadata) with a registrationId that is not present in the configured RelyingPartyRegistrationRepository, or one whose repository lookup returns null.","commonSituations":"Typo or case mismatch in the registrationId in the URL; the registration was renamed or removed from application.yml / RelyingPartyRegistrationRepository bean; the app serves multiple tenants and the request uses an id registered in a different environment (dev vs prod); the repository is a CachingIterableRelyingPartyRegistrationRepository that hasn't loaded metadata for that id yet.","solutions":["Fix the registrationId in the request URL to match exactly an id registered in RelyingPartyRegistrationRepository (check application.yml spring.security.saml2.relyingparty.registration.* keys).","Verify the RelyingPartyRegistrationRepository bean actually contains the registration (log repository size or enumerate registrations).","Confirm the request is reaching the right application/environment where the registration is configured.","If dynamic resolution is expected, implement a custom RelyingPartyRegistrationResolver that creates registrations on demand instead of relying on a static repository.","Catch Saml2Exception in a filter/error handler and return HTTP 404 rather than a 500 for unknown registration ids."],"exampleFix":"// before (application.yml)\nspring.security.saml2.relyingparty.registration:\n  idp-prod:\n    assertingparty.metadata-uri: https://idp.example.com/metadata\n// request: GET /saml2/metadata/prod-idp  -> Saml2Exception\n// after\n// request with matching id:\n// GET /saml2/metadata/idp-prod -> metadata XML returned","handlingStrategy":"try-catch","validationCode":"String regId = matcher.getVariables().get(\"registrationId\");\nRelyingPartyRegistration r = registrations.resolve(request, regId);\nif (r == null) { response.sendError(404); return; }","typeGuard":"boolean isKnownRegistration(String id) {\n    try { return relyingPartyRegistrations.findByRegistrationId(id) != null; }\n    catch (Exception e) { return false; }\n}","tryCatchPattern":"try {\n    return metadataFilterChain.doFilter(request, response);\n} catch (Saml2Exception ex) {\n    if (String.valueOf(ex.getMessage()).contains(\"registration not found\")) {\n        response.sendError(HttpServletResponse.SC_NOT_FOUND);\n    } else { throw ex; }\n}","preventionTips":["Keep registrationIds stable and share them with the IdP/partners as the exact metadata URL","Add an integration test hitting /saml2/metadata/{id} for every configured registration","Monitor 404s on the metadata endpoint to catch renamed registrations"],"tags":["saml2","spring-security","config","metadata"],"backgroundTag":"resource-not-found","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}