{"record":{"id":"71f550cfd93a4f72","repo":"flowable/flowable-engine","slug":"createdafter-is-null","errorCode":null,"errorMessage":"createdAfter is null","messagePattern":"createdAfter is null","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/PlanItemInstanceQueryImpl.java","lineNumber":350,"sourceCode":"    }\n\n    @Override\n    public PlanItemInstanceQuery planItemInstanceCreatedBefore(Date createdBefore) {\n        if (createdBefore == null) {\n            throw new FlowableIllegalArgumentException(\"createdBefore is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.createdBefore = createdBefore;\n        } else {\n            this.createdBefore = createdBefore;\n        }\n        return this;\n    }\n\n    @Override\n    public PlanItemInstanceQuery planItemInstanceCreatedAfter(Date createdAfter) {\n        if (createdAfter == null) {\n            throw new FlowableIllegalArgumentException(\"createdAfter is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.createdAfter = createdAfter;\n        } else {\n            this.createdAfter = createdAfter;\n        }\n        return this;\n    }\n\n    @Override\n    public PlanItemInstanceQuery planItemInstanceLastAvailableBefore(Date availableBefore) {\n        if (availableBefore == null) {\n            throw new FlowableIllegalArgumentException(\"availableBefore is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.lastAvailableBefore = availableBefore;\n        } else {\n            this.lastAvailableBefore = availableBefore;","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/PlanItemInstanceQueryImpl.java#L332-L368","documentation":"Thrown by PlanItemInstanceQueryImpl.planItemInstanceCreatedAfter when the createdAfter Date is null. The engine requires a concrete date for the lower bound of the created-time filter and rejects null at builder time.","triggerScenarios":"Calling planItemInstanceCreatedAfter(null), commonly when the range start comes from a nullable request parameter or a failed date parse.","commonSituations":"'since' filter omitted in an API call; a JSON date field missing in the payload mapped to null; calendar/date arithmetic producing null on error paths.","solutions":["Pass a valid java.util.Date for the lower bound.","Null-check and skip the filter when the caller did not specify a start date.","Use planItemInstanceCreatedBefore for the upper bound and combine both for a bounded range."],"exampleFix":"// before\nquery.planItemInstanceCreatedAfter(range.getStart()); // may be null\n// after\nif (range.getStart() != null) {\n    query.planItemInstanceCreatedAfter(range.getStart());\n}","handlingStrategy":"validation","validationCode":"if (createdAfter != null) {\n    planItemInstanceQuery.planItemInstanceCreatedAfter(createdAfter);\n} // else: unbounded start","typeGuard":"boolean isPresent(Date d) {\n    return d != null;\n}","tryCatchPattern":"try {\n    query.planItemInstanceCreatedAfter(createdAfter);\n} catch (FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"createdAfter is null\")) {\n        // omit the lower bound and continue\n    } else {\n        throw e;\n    }\n}","preventionTips":["Treat optional range bounds as conditional filters, not null-passing calls","Use java.time parsers that throw on invalid input","Validate request date fields before query construction"],"tags":["cmmn","query","null-argument","date","flowable"],"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"}