{"record":{"id":"28f8122a838102f9","repo":"flowable/flowable-engine","slug":"involveduser-is-null-28f812","errorCode":null,"errorMessage":"involvedUser is null","messagePattern":"involvedUser is null","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricPlanItemInstanceQueryImpl.java","lineNumber":359,"sourceCode":"    }\n    \n    @Override\n    public HistoricPlanItemInstanceQuery planItemInstanceExtraValue(String extraValue) {\n        if (extraValue == null) {\n            throw new FlowableIllegalArgumentException(\"extraValue is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.extraValue = extraValue;\n        } else {\n            this.extraValue = extraValue;\n        }\n        return this;\n    }\n    \n    @Override\n    public HistoricPlanItemInstanceQuery involvedUser(String involvedUser) {\n        if (involvedUser == null) {\n            throw new FlowableIllegalArgumentException(\"involvedUser is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.involvedUser = involvedUser;\n        } else {\n            this.involvedUser = involvedUser;\n        }\n        return this;\n    }\n    \n    @Override\n    public HistoricPlanItemInstanceQuery involvedGroups(Collection<String> involvedGroups) {\n        if (involvedGroups == null) {\n            throw new FlowableIllegalArgumentException(\"involvedGroups is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.involvedGroups = involvedGroups;\n        } else {\n            this.involvedGroups = involvedGroups;","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricPlanItemInstanceQueryImpl.java#L341-L377","documentation":"HistoricPlanItemInstanceQuery.involvedUser() requires a non-null user id string. Flowable throws FlowableIllegalArgumentException when null is passed because an involvement filter with null user would produce meaningless SQL. The value is applied either to the main query or the current OR-query object depending on inOrStatement.","triggerScenarios":"Calling historicPlanItemInstanceQuery.involvedUser(null), typically involvedUser(authenticatedUserId) where the security context has no authenticated user, or involvedUser(params.get(\"userId\")) with a missing request parameter.","commonSituations":"Building 'my tasks' style history views while the user session expired (userId resolves to null); REST endpoints where the userId path/query param was omitted; background jobs running without an authenticated principal.","solutions":["Pass a valid non-null user id that has an identity link (involvement) on the plan item instance.","Resolve the current user before building the query and fail earlier with a clear application-level message if absent.","Skip the involvedUser filter when no user is available rather than calling it with null.","Verify the user actually has involvement records (identity links) if you get empty results after fixing the null."],"exampleFix":"// before\nquery.involvedUser(SecurityUtils.getCurrentUserId());\n\n// after\nString userId = SecurityUtils.getCurrentUserId();\nif (userId != null) {\n    query.involvedUser(userId);\n} else {\n    throw new IllegalStateException(\"User must be authenticated to query involved plan items\");\n}","handlingStrategy":"validation","validationCode":"String userId = SecurityUtils.getCurrentUserId();\nif (userId == null || userId.isEmpty()) {\n    throw new IllegalStateException(\"Authenticated user id is required\");\n}\nquery.involvedUser(userId);","typeGuard":"boolean hasInvolvedUser(HistoricPlanItemInstance p, String userId) {\n    return p != null && userId != null && !userId.isEmpty();\n}","tryCatchPattern":"try {\n    query.involvedUser(userId);\n} catch (FlowableIllegalArgumentException e) {\n    log.warn(\"Invalid involvedUser filter: {}\", e.getMessage());\n    // reject request with 400 or re-query without the filter\n}","preventionTips":["Resolve the authenticated principal before building the query and handle 'no user' as a distinct case.","Require userId explicitly in endpoints instead of deriving it lazily from the security context.","Remember involvedUser filters on identity links; the user must have been added via userIdentityLink.","Wrap Flowable query building in a shared validation helper."],"tags":["flowable","cmmn","query","null-argument","identity-links"],"backgroundTag":"null-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}