{"record":{"id":"a58158e53d86dc60","repo":"keycloak/keycloak","slug":"permission-id-must-not-be-null","errorCode":null,"errorMessage":"Permission id must not be null","messagePattern":"Permission id must not be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"authz/client/src/main/java/org/keycloak/authorization/client/resource/PolicyResource.java","lineNumber":90,"sourceCode":"        try {\n            return callable.call();\n        } catch (Exception cause) {\n            return Throwables.retryAndWrapExceptionIfNecessary(callable, pat, \"Error creating policy for resource [\" + resourceId + \"]\", cause);\n        }\n    }\n\n    /**\n     * Updates an existing user-managed permission\n     *\n     * @param permission the permission to update\n     */\n    public void update(final UmaPermissionRepresentation permission) {\n        if (permission == null) {\n            throw new IllegalArgumentException(\"Permission must not be null\");\n        }\n\n        if (permission.getId() == null) {\n            throw new IllegalArgumentException(\"Permission id must not be null\");\n        }\n\n        Callable<Void> callable = new Callable<Void>() {\n            @Override\n            public Void call() throws Exception {\n                http.<Void>put(serverConfiguration.getPolicyEndpoint() + \"/\"+ encodePathAsIs(permission.getId()))\n                        .authorizationBearer(pat.call())\n                        .json(JsonSerialization.writeValueAsBytes(permission)).execute();\n                return null;\n            }\n        };\n        try {\n            callable.call();\n        } catch (Exception cause) {\n            Throwables.retryAndWrapExceptionIfNecessary(callable, pat, \"Error updating policy for resource [\" + resourceId + \"]\", cause);\n        }\n    }\n","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/keycloak/keycloak/blob/66c7e15a3788de7764f07dd2558275a02770e16d/authz/client/src/main/java/org/keycloak/authorization/client/resource/PolicyResource.java#L72-L108","documentation":"Thrown by PolicyResource.update(UmaPermissionRepresentation) when the permission is non-null but getId() returns null. The permission ID is used directly in the URL path of the PUT request (policy endpoint + / + encodedId). Without it, the server cannot identify which policy to update.","triggerScenarios":"Constructing a new UmaPermissionRepresentation locally (which has no server-assigned ID) and calling update() on it. Loading a permission from an external/serialized source where the id field was not populated.","commonSituations":"Confusing create() semantics with update() — building a fresh permission object and trying to update it. JSON deserialization that omits or misnames the id field.","solutions":["Load the existing permission via findById(id) first to get its server-assigned ID, then modify and update","If the ID is known from another source, set it: permission.setId(existingId) before calling update()"],"exampleFix":"// before\nUmaPermissionRepresentation perm = new UmaPermissionRepresentation();\nperm.setName(\"Updated Policy\");\npolicyResource.update(perm); // throws — no id\n\n// after\nUmaPermissionRepresentation perm = policyResource.findById(existingPolicyId);\nperm.setName(\"Updated Policy\");\npolicyResource.update(perm);","handlingStrategy":"validation","validationCode":"// Ensure permission has an ID before updating\nUmaPermissionRepresentation permission = loadPermission();\nif (permission == null || permission.getId() == null) {\n    throw new IllegalStateException(\n        \"Cannot update UMA permission without a server-assigned ID\");\n}\npolicyResource.update(permission);","typeGuard":"public static boolean hasValidPermissionId(UmaPermissionRepresentation permission) {\n    return permission != null && permission.getId() != null;\n}","tryCatchPattern":null,"preventionTips":["Never manually construct a UmaPermissionRepresentation for update — always load it from the server first","If deserializing from JSON, validate that the id field is present and non-null"],"tags":["policy","authz-client","validation","update","uma"],"backgroundTag":null,"analyzedSha":"66c7e15a3788de7764f07dd2558275a02770e16d","analyzedAt":"2026-08-14T01:36:42.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}