{"record":{"id":"24150c11bf3c2b52","repo":"flowable/flowable-engine","slug":"formkey-is-null","errorCode":null,"errorMessage":"formKey is null","messagePattern":"formKey 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":333,"sourceCode":"    }\n\n    @Override\n    public HistoricPlanItemInstanceQuery planItemInstanceExitCriterionId(String exitCriterionId) {\n        if (exitCriterionId == null) {\n            throw new FlowableIllegalArgumentException(\"ExitCriterionId is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.exitCriterionId = exitCriterionId;\n        } else {\n            this.exitCriterionId = exitCriterionId;\n        }\n        return this;\n    }\n    \n    @Override\n    public HistoricPlanItemInstanceQuery planItemInstanceFormKey(String formKey) {\n        if (formKey == null) {\n            throw new FlowableIllegalArgumentException(\"formKey is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.formKey = formKey;\n        } else {\n            this.formKey = formKey;\n        }\n        return this;\n    }\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;","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricPlanItemInstanceQueryImpl.java#L315-L351","documentation":"HistoricPlanItemInstanceQuery.planItemInstanceFormKey() requires a non-null formKey string. Flowable throws FlowableIllegalArgumentException when null is passed because a null would be ambiguous with the field simply not being set, so the query API rejects it eagerly instead of generating incorrect SQL.","triggerScenarios":"Calling historicPlanItemInstanceQuery.planItemInstanceFormKey(null), e.g. planItemInstanceFormKey(task.getFormKey()) where the task/form definition has no form key, or a lookup of the form key in a properties/JSON config returned null.","commonSituations":"Filtering historic plan items by form key when some case definitions have no form key configured; passing user task formKey from a task that was created without one; forwarding a formKey field from an API request body where the client omitted it.","solutions":["Pass the actual non-null form key string configured on the user task / form definition.","Guard the call: only invoke planItemInstanceFormKey when the value is non-null; otherwise omit the filter.","If searching for items without a form key is intended, apply that filter in application code after the query.","Verify the case/user-task model actually defines a formKey if one is expected."],"exampleFix":"// before\nquery.planItemInstanceFormKey(request.getFormKey());\n\n// after\nif (request.getFormKey() != null) {\n    query.planItemInstanceFormKey(request.getFormKey());\n}","handlingStrategy":"validation","validationCode":"if (formKey == null || formKey.isEmpty()) {\n    throw new IllegalArgumentException(\"formKey must be provided\");\n}\nquery.planItemInstanceFormKey(formKey);","typeGuard":"boolean hasFormKey(HistoricPlanItemInstance p) {\n    return p != null && p.getFormKey() != null;\n}","tryCatchPattern":"try {\n    query.planItemInstanceFormKey(formKey);\n} catch (FlowableIllegalArgumentException e) {\n    log.warn(\"Invalid formKey filter: {}\", e.getMessage());\n    // omit filter or surface validation error to caller\n}","preventionTips":["Null-check formKey sources (task instances, config lookups, request params) before filtering.","Model user tasks without form keys explicitly so callers know the value may be absent.","Use @NotNull/@NotBlank bean validation on formKey in REST request DTOs.","Skip optional filters instead of calling query methods with null."],"tags":["flowable","cmmn","query","null-argument","form-key"],"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"}