{"record":{"id":"547dcb68f6281f89","repo":"keycloak/keycloak","slug":"error-while-updating-policy-client-scope","errorCode":null,"errorMessage":"Error while updating policy [{}]. Client Scope [{}] could not be found.","messagePattern":"Error while updating policy \\[(.+?)\\]\\. Client Scope \\[(.+?)\\] could not be found\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/clientscope/ClientScopePolicyProviderFactory.java","lineNumber":238,"sourceCode":"    }\n\n    private void updateClientScopes(Policy policy, AuthorizationProvider authorization,\n        Set<ClientScopeDefinition> clientScopes) {\n        RealmModel realm = authorization.getRealm();\n        Set<ClientScopePolicyRepresentation.ClientScopeDefinition> updatedClientScopes = new HashSet<>();\n\n        if (clientScopes != null) {\n            for (ClientScopePolicyRepresentation.ClientScopeDefinition definition : clientScopes) {\n                String clientScopeName = definition.getId();\n                ClientScopeModel clientScope = realm.getClientScopesStream()\n                    .filter(scope -> scope.getName().equals(clientScopeName)).findAny().orElse(null);\n\n                if (clientScope == null) {\n                    clientScope = realm.getClientScopeById(clientScopeName);\n                }\n\n                if (clientScope == null) {\n                    throw new RuntimeException(\n                        \"Error while updating policy [\" + policy.getName() + \"]. Client Scope [\" + \"] could not be found.\");\n                }\n\n                definition.setId(clientScope.getId());\n                updatedClientScopes.add(definition);\n            }\n        }\n\n        try {\n            policy.putConfig(\"clientScopes\", JsonSerialization.writeValueAsString(updatedClientScopes));\n        } catch (IOException e) {\n            throw new RuntimeException(\"Failed to serialize client scopes\", e);\n        }\n    }\n}\n","sourceCodeStart":220,"sourceCodeEnd":254,"githubUrl":"https://github.com/keycloak/keycloak/blob/66c7e15a3788de7764f07dd2558275a02770e16d/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/clientscope/ClientScopePolicyProviderFactory.java#L220-L254","documentation":"Thrown by ClientScopePolicyProviderFactory.updateClientScopes() when a referenced client scope cannot be resolved by name (realm.getClientScopesStream().filter(name == clientScopeName)) nor by id (realm.getClientScopeById(clientScopeName)). NOTE: there is a source bug — the message string is \"Client Scope [\" + \"] could not be found.\" which omits the clientScopeName variable, so the brackets are always empty in the rendered message. The actual offending scope name is in the local variable clientScopeName but never interpolated.","triggerScenarios":"Creating or updating a 'client-scope' policy whose clientScopes reference a scope name or id that does not exist in the realm. The lookup tries name first, then falls back to id; both failing raises this. Because of the message bug, you cannot read the offending name from the exception text — you must inspect the request/representation directly.","commonSituations":"Typo in a client scope name; the client scope was deleted after the policy was last edited; cross-realm confusion; using an id where a name is expected (or vice-versa) that doesn't match either; import referencing scopes not present in the target realm.","solutions":["Since the message is empty, log the inbound representation's clientScope names/ids yourself before calling update to identify the bad reference.","Validate each definition.getId() resolves via name or id in the target realm before update.","Correct typos or remove stale references; ensure scopes exist (create them first if importing)."],"exampleFix":"// before: update throws with an empty 'Client Scope []' (source bug hides the name)\nrep.setClientScopes(Collections.singleton(definitionWithName(\"public-scope-typo\")));\nauthz.policies().update(rep);\n\n// after: validate each scope reference before update, surfacing the real name\nRealmModel realm = authorization.getRealm();\nfor (ClientScopeDefinition d : rep.getClientScopes()) {\n    String n = d.getId();\n    boolean exists = realm.getClientScopesStream().anyMatch(s -> s.getName().equals(n))\n                 || realm.getClientScopeById(n) != null;\n    if (!exists) throw new IllegalArgumentException(\"unknown client scope: \" + n);\n}\nauthz.policies().update(rep);","handlingStrategy":"validation","validationCode":"// Validate each client scope reference resolves (name then id) before update\nRealmModel realm = authorization.getRealm();\nfor (ClientScopeDefinition d : rep.getClientScopes()) {\n    String n = d.getId();\n    boolean exists = realm.getClientScopesStream().anyMatch(s -> s.getName().equals(n))\n                 || realm.getClientScopeById(n) != null;\n    if (!exists) throw new IllegalArgumentException(\"unknown client scope: \" + n);\n}","typeGuard":"private boolean clientScopeResolves(RealmModel realm, String nameOrId) {\n    return realm.getClientScopesStream().anyMatch(s -> s.getName().equals(nameOrId))\n        || realm.getClientScopeById(nameOrId) != null;\n}","tryCatchPattern":"// The exception message is buggy (empty brackets); validate yourself.\nfor (ClientScopeDefinition d : rep.getClientScopes()) {\n    if (!clientScopeResolves(realm, d.getId()))\n        throw new IllegalArgumentException(\"unknown client scope: \" + d.getId());\n}\nauthz.policies().update(rep);","preventionTips":["Because the source message omits the scope name, log the inbound definitions yourself before update.","Resolve scope references (name then id) before creating/updating client-scope policies.","Create referenced client scopes before importing policies that use them."],"tags":["policy","clientscope-policy","validation","scope-lookup","reference","bug"],"backgroundTag":null,"analyzedSha":"66c7e15a3788de7764f07dd2558275a02770e16d","analyzedAt":"2026-08-14T01:36:42.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}