{"record":{"id":"3f54f272132236d5","repo":"keycloak/keycloak","slug":"failed-to-serialize-groups","errorCode":null,"errorMessage":"Failed to serialize groups","messagePattern":"Failed to serialize groups","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/group/GroupPolicyProviderFactory.java","lineNumber":190,"sourceCode":"        if (groupsClaim != null) {\n            config.put(\"groupsClaim\", groupsClaim);\n        }\n\n        for (GroupPolicyRepresentation.GroupDefinition definition : groups) {\n            GroupModel group = getGroup(authorization, definition);\n\n            if (group == null) {\n                continue;\n            }\n\n            definition.setId(group.getId());\n            definition.setPath(null);\n        }\n\n        try {\n            config.put(\"groups\", JsonSerialization.writeValueAsString(groups));\n        } catch (IOException cause) {\n            throw new RuntimeException(\"Failed to serialize groups\", cause);\n        }\n\n        policy.setConfig(config);\n    }\n\n    private GroupModel getGroup(AuthorizationProvider authorization, GroupDefinition definition) {\n        RealmModel realm = authorization.getRealm();\n        KeycloakSession session = authorization.getKeycloakSession();\n        GroupProvider groups = session.groups();\n\n        if (definition.getId() != null) {\n            GroupModel group = realm.getGroupById(definition.getId());\n\n            // Validate that only REALM groups can be used in authorization policies\n            if (group != null && GroupModel.Type.ORGANIZATION.equals(group.getType())) {\n                throw new BadRequestException(\"Organization groups cannot be used. Only realm groups are allowed.\");\n            }\n","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/keycloak/keycloak/blob/66c7e15a3788de7764f07dd2558275a02770e16d/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/group/GroupPolicyProviderFactory.java#L172-L208","documentation":"Thrown by GroupPolicyProviderFactory.updatePolicy() when Jackson fails to serialize the processed groups set into the policy config during create or update. After resolving group definitions to valid group IDs and clearing paths, the code calls JsonSerialization.writeValueAsString(groups) to persist them. An IOException here means the in-memory group definitions could not be written to JSON.","triggerScenarios":"POST or PUT to create/update a group policy where the group definitions, after server-side processing (id resolution, path clearing), produce objects that Jackson cannot serialize.","commonSituations":"Very rare. Usually indicates an internal bug, a Jackson ObjectMapper misconfiguration in a custom deployment, or a GroupDefinition subclass with non-serializable fields. Could also occur under extreme memory pressure.","solutions":["Check the wrapped IOException cause in the server log for the exact serialization failure point.","Verify the group definitions being submitted use standard fields (id, path) and not unexpected nested objects.","If using a custom Keycloak build, ensure GroupDefinition and its fields are Jackson-serializable.","Retry the operation; if it persists, recreate the policy from scratch."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    factory.onCreate(policy, rep, authorization);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Failed to serialize groups\")) {\n        logger.error(\"Serialization failure for group policy\", e.getCause());\n        // retry or alert — likely an internal issue\n    } else {\n        throw e;\n    }\n}","preventionTips":["Ensure GroupDefinition objects only contain standard types (String id, String path).","In custom builds, verify Jackson can serialize GroupDefinition via a unit test.","Monitor for this error in production logs — its presence usually signals a build or plugin issue."],"tags":["keycloak","authorization","json-serialization","group-policy"],"backgroundTag":null,"analyzedSha":"66c7e15a3788de7764f07dd2558275a02770e16d","analyzedAt":"2026-08-14T01:36:42.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}