{"record":{"id":"55f5790087ccd5b1","repo":"apereo/cas","slug":"unable-to-determine-entity-id-to-fetch-metadata-vi","errorCode":null,"errorMessage":"Unable to determine entity id to fetch metadata via MDQ for ","messagePattern":"Unable to determine entity id to fetch metadata via MDQ for ","errorType":"exception","errorClass":"SamlException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-saml-idp-metadata/src/main/java/org/apereo/cas/support/saml/services/idp/metadata/cache/resolver/MetadataQueryProtocolMetadataResolver.java","lineNumber":121,"sourceCode":"            .proxyUrl(service.getMetadataProxyLocation())\n            .build();\n        val response = HttpUtils.execute(exec);\n        if (response == null || HttpStatus.resolve(response.getCode()).is5xxServerError()) {\n            LOGGER.error(\"Unable to fetch metadata from [{}]\", metadataLocation);\n            throw UnauthorizedServiceException.denied(\"Rejected: %s\".formatted(metadataLocation));\n        }\n        return response;\n    }\n\n    @Override\n    protected Set<String> getMetadataLocationsForService(final SamlRegisteredService service, final CriteriaSet criteriaSet) {\n        LOGGER.trace(\"Getting metadata location dynamically for [{}] based on criteria [{}]\", service.getName(), criteriaSet);\n        val entityIdCriteria = criteriaSet.get(EntityIdCriterion.class);\n        val entityId = Optional.ofNullable(entityIdCriteria)\n            .map(EntityIdCriterion::getEntityId)\n            .orElseGet(service::getServiceId);\n        if (StringUtils.isBlank(entityId)) {\n            throw new SamlException(\"Unable to determine entity id to fetch metadata via MDQ for \" + service.getName());\n        }\n        val locations = super.getMetadataLocationsForService(service, criteriaSet);\n        return locations\n            .stream()\n            .map(location -> location.replace(\"{0}\", EncodingUtils.urlEncode(entityId)))\n            .collect(Collectors.toCollection(LinkedHashSet::new));\n    }\n\n    private static void setFileAttribute(final HttpResponse response, final File backupFile) {\n        FunctionUtils.doAndHandle(t -> {\n            val path = backupFile.toPath();\n            val etag = response.getFirstHeader(\"ETag\").getValue();\n            Files.setAttribute(path, \"user:ETag\", ByteBuffer.wrap(etag.getBytes(StandardCharsets.UTF_8)));\n        });\n    }\n}\n","sourceCodeStart":103,"sourceCodeEnd":138,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-saml-idp-metadata/src/main/java/org/apereo/cas/support/saml/services/idp/metadata/cache/resolver/MetadataQueryProtocolMetadataResolver.java#L103-L138","documentation":"Thrown before issuing an MDQ query when no entityID can be determined for the request. The resolver takes the EntityIdCriterion from the criteria set, falling back to the registered service's serviceId; if both are blank there is nothing to query.","triggerScenarios":"Calling getMetadataLocationsForService with a criteria set lacking EntityIdCriterion AND a SamlRegisteredService whose getServiceId() is blank/empty (e.g. service defined with empty serviceId pattern).","commonSituations":"SAML service registered without a serviceId/entityID; programmatic criteria built without EntityIdCriterion builder; regex-based service whose serviceId does not carry the entityID; import/migration left the field empty.","solutions":["Set the serviceId (entityID) on the SamlRegisteredService definition.","Include an EntityIdCriterion in the criteria set: new CriteriaSet(new EntityIdCriterion(entityId)).","Fix service registry import/export so the service has a non-blank serviceId.","Log the service definition to confirm which registered service has the blank id."],"exampleFix":"// before\nval criteriaSet = new CriteriaSet(new EntityIdCriterion(\"\"));\n// after\nval criteriaSet = new CriteriaSet(new EntityIdCriterion(\"https://sp.example.org/metadata\"));","handlingStrategy":"validation","validationCode":"val entityId = Optional.ofNullable(criteriaSet.get(EntityIdCriterion.class))\n    .map(EntityIdCriterion::getEntityId).orElseGet(service::getServiceId);\nif (StringUtils.isBlank(entityId)) throw new IllegalArgumentException(\"Register service with non-blank serviceId before MDQ resolution\");","typeGuard":"boolean hasEntityId(SamlRegisteredService s) { return s != null && StringUtils.isNotBlank(s.getServiceId()); }","tryCatchPattern":"try {\n    return mdqResolver.resolve(criteriaSet);\n} catch (SamlException e) {\n    LOGGER.error(\"No entityID for service [{}]\", service.getName(), e);\n    return Set.of();\n}","preventionTips":["Always set serviceId to the SP entityID when registering SAML services.","Validate service registry entries after import/migration.","Include EntityIdCriterion explicitly when building criteria sets programmatically.","Add a startup check that logs SAML services with blank serviceIds."],"tags":["saml","mdq","metadata","configuration","entity-id"],"backgroundTag":"missing-required-config-field","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}