{"record":{"id":"e32464a3471c3144","repo":"flowable/flowable-engine","slug":"after-time-is-null-e32464","errorCode":null,"errorMessage":"after time is null","messagePattern":"after 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":556,"sourceCode":"\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 {\n            this.startedAfter = afterTime;\n        }\n        return this;\n    }\n\n    @Override\n    public CaseInstanceQueryImpl caseInstanceStartedBy(String userId) {\n        if (userId == null) {\n            throw new FlowableIllegalArgumentException(\"user id is null\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.startedBy = userId;\n        } else {\n            this.startedBy = userId;","sourceCodeStart":538,"sourceCodeEnd":574,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceQueryImpl.java#L538-L574","documentation":"Flowable throws this FlowableIllegalArgumentException when CaseInstanceQueryImpl.caseInstanceStartedAfter(Date) receives a null afterTime. The started-after filter is the lower bound of the start-time range; a null bound cannot be translated to SQL, so it is rejected eagerly.","triggerScenarios":"Calling caseInstanceQuery.caseInstanceStartedAfter(null) directly, or supplying a Date that was never initialized because parsing/lookup failed.","commonSituations":"Dashboard 'started since' filters left empty by users; REST query parameters mapped to null; computing a since-date from config with a missing key.","solutions":["Pass a valid java.util.Date lower bound","Omit the startedAfter call when no lower bound is needed","Provide a sensible default (e.g. epoch or now minus retention window) when the input is absent"],"exampleFix":"// before\nquery.caseInstanceStartedAfter(sinceDate); // throws when sinceDate == null\n// after\nif (sinceDate != null) {\n    query.caseInstanceStartedAfter(sinceDate);\n}","handlingStrategy":"validation","validationCode":"Date after = parseDate(afterStr);\nif (after != null) {\n    query.caseInstanceStartedAfter(after);\n}","typeGuard":"boolean isValidBound(Date d) { return d != null; }","tryCatchPattern":"try {\n    query.caseInstanceStartedAfter(after);\n} catch (FlowableIllegalArgumentException e) {\n    log.warn(\"Skipping started-after filter: {}\", e.getMessage());\n}","preventionTips":["Default missing 'since' inputs to a defined epoch or retention start","Validate parsed dates before passing to builders","Wrap filter application in helper methods that null-guard all bounds"],"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-14T16:17:12.679Z"}