{"record":{"id":"bb76531cfcd58eee","repo":"apereo/cas","slug":"cannot-save-a-resource-set-with-inconsistent-scope","errorCode":null,"errorMessage":"Cannot save a resource set with inconsistent scopes.","messagePattern":"Cannot save a resource set with inconsistent scopes\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-oauth-uma-core/src/main/java/org/apereo/cas/uma/ticket/resource/repository/BaseResourceSetRepository.java","lineNumber":33,"sourceCode":"        return getAll().stream()\n            .filter(s -> s.getOwner().equalsIgnoreCase(owner)).collect(Collectors.toSet());\n    }\n\n    @Override\n    public Collection<ResourceSet> getByClient(final String clientId) {\n        return getAll().stream()\n            .filter(s -> s.getClientId().equalsIgnoreCase(clientId)).collect(Collectors.toSet());\n    }\n\n    @Override\n    public long count() {\n        return getAll().size();\n    }\n\n    @Override\n    public ResourceSet save(final ResourceSet set) {\n        if (!validateResourceSetScopes(set)) {\n            throw new IllegalArgumentException(\"Cannot save a resource set with inconsistent scopes.\");\n        }\n        return saveInternal(set);\n    }\n\n    @Override\n    public ResourceSet update(final ResourceSet currentResource, final ResourceSet newResource) {\n        if (currentResource.getId() <= 0 || newResource.getId() <= 0) {\n            throw new IllegalArgumentException(\"Cannot update a resource set without identifiers.\");\n        }\n        if (currentResource.getId() != newResource.getId()) {\n            throw new IllegalArgumentException(\"Cannot update a resource set with inconsistent/mismatched identifiers.\");\n        }\n        if (!validateResourceSetScopes(newResource)) {\n            throw new IllegalArgumentException(\"Cannot save a resource set with inconsistent scopes.\");\n        }\n\n        currentResource.setOwner(newResource.getOwner());\n        currentResource.setClientId(newResource.getClientId());","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-oauth-uma-core/src/main/java/org/apereo/cas/uma/ticket/resource/repository/BaseResourceSetRepository.java#L15-L51","documentation":"Thrown by BaseResourceSetRepository.save when the UMA ResourceSet's registered scope list does not correspond to scopes the repository accepts (validateResourceSetScopes fails). CAS requires that a resource set only advertise scopes it can associate with authorization policies; inconsistent scopes would break later permission-ticket issuance. The repository refuses to persist the resource set in that case.","triggerScenarios":"Calling save(ResourceSet) with a resource set whose scopes contain values not registered/allowed by the configured scope validator (e.g. scopes missing from the UMA resource-set scope registry or service definition).","commonSituations":"Registering a UMA resource set via the UMA resource-set-registration endpoint with scopes the client has not declared; typos or case mismatches in scope names; after an admin removed scopes from configuration that existing clients still request.","solutions":["Ensure every scope in the ResourceSet is registered in the CAS UMA/service scope configuration before saving.","Fix scope name spelling and casing to match configured scopes exactly.","Add the missing scopes to the service definition or UMA scope configuration if they are legitimately needed.","Catch IllegalArgumentException around save() and return a 400 invalid_scope response to the client."],"exampleFix":"// before\nResourceSet set = new ResourceSet();\nset.setScopes(Set.of(\"read\", \"writ\")); // typo not registered\nrepository.save(set); // throws\n// after\nResourceSet set = new ResourceSet();\nset.setScopes(Set.of(\"read\", \"write\")); // matches configured scopes\nrepository.save(set);","handlingStrategy":"validation","validationCode":"Set<String> registered = umaConfiguration.getRegisteredScopes();\nif (!set.getScopes().stream().allMatch(registered::contains)) {\n    throw new IllegalArgumentException(\"ResourceSet has unregistered scopes\");\n}","typeGuard":null,"tryCatchPattern":"try { repository.save(set); } catch (IllegalArgumentException e) {\n    return ResponseEntity.badRequest().body(Map.of(\"error\", \"invalid_scope\"));\n}","preventionTips":["Keep a single source of truth for UMA scopes and validate client payloads against it","Normalize scope casing before persisting","Write an integration test that saves resource sets with each registered scope"],"tags":["uma","oauth","scope-validation","invalid-argument"],"backgroundTag":"invalid-argument-value","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"}