{"record":{"id":"7673bc81da8c52a5","repo":"flowable/flowable-engine","slug":"before-time-is-null-7673bc","errorCode":null,"errorMessage":"before time is null","messagePattern":"before time is null","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceQueryImpl.java","lineNumber":542,"sourceCode":"    }\n\n    @Override\n    public CaseInstanceQueryImpl caseInstanceParentId(String parentId) {\n        if (parentId == null) {\n            throw new FlowableIllegalArgumentException(\"Parent id is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.caseInstanceParentId = parentId;\n        } else {\n            this.caseInstanceParentId = parentId;\n        }\n        return this;\n    }\n\n    @Override\n    public CaseInstanceQueryImpl caseInstanceStartedBefore(Date beforeTime) {\n        if (beforeTime == null) {\n            throw new FlowableIllegalArgumentException(\"before time is null\");\n        }\n\n        if (inOrStatement) {\n            this.currentOrQueryObject.startedBefore = beforeTime;\n        } else {\n            this.startedBefore = beforeTime;\n        }\n        return this;\n    }\n\n    @Override\n    public CaseInstanceQueryImpl caseInstanceStartedAfter(Date afterTime) {\n        if (afterTime == null) {\n            throw new FlowableIllegalArgumentException(\"after time is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.startedAfter = afterTime;\n        } else {","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceQueryImpl.java#L524-L560","documentation":"Flowable throws this FlowableIllegalArgumentException when CaseInstanceQueryImpl.caseInstanceStartedBefore(Date) receives a null beforeTime. The started-before filter bounds the query's start-time comparison in SQL; a null bound is ambiguous and rejected at query-construction time.","triggerScenarios":"Calling caseInstanceQuery.caseInstanceStartedBefore(null) directly, or passing a Date parsed from user input/REST parameter that failed to parse or was absent.","commonSituations":"Date-range search UIs where the 'before' field is optional; converting a null String date via a formatter that returns null; timezone/parse failures yielding a null Date.","solutions":["Pass a valid java.util.Date (e.g. new Date() or a parsed value)","Omit the startedBefore filter when no upper bound is desired","Null-check the parsed date before applying the filter"],"exampleFix":"// before\nquery.caseInstanceStartedBefore(parseDate(beforeStr)); // parseDate may return null\n// after\nDate before = parseDate(beforeStr);\nif (before != null) {\n    query.caseInstanceStartedBefore(before);\n}","handlingStrategy":"validation","validationCode":"Date before = parseDate(beforeStr);\nif (before != null) {\n    query.caseInstanceStartedBefore(before);\n}","typeGuard":"boolean isPastBound(Date d) { return d != null; }","tryCatchPattern":"try {\n    query.caseInstanceStartedBefore(before);\n} catch (FlowableIllegalArgumentException e) {\n    log.warn(\"Skipping started-before filter: {}\", e.getMessage());\n}","preventionTips":["Return Optional<Date> from date parsers instead of null","Make optional date filters conditional in the query builder chain","Use java.time types internally and convert to Date at the last moment"],"tags":["flowable","cmmn","null-argument","date-filter"],"backgroundTag":"null-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}