{"record":{"id":"8b1fa9592f66fdd2","repo":"flowable/flowable-engine","slug":"callbackids-is-null-or-empty-8b1fa9","errorCode":null,"errorMessage":"callbackIds is null or empty","messagePattern":"callbackIds is null or empty","errorType":"exception","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/HistoricProcessInstanceQueryImpl.java","lineNumber":769,"sourceCode":"            this.nameLikeIgnoreCase = nameLikeIgnoreCase.toLowerCase();\n        }\n        return this;\n    }\n    \n    @Override\n    public HistoricProcessInstanceQuery processInstanceCallbackId(String callbackId) {\n        if (inOrStatement) {\n            currentOrQueryObject.callbackId = callbackId;\n        } else {\n            this.callbackId = callbackId;\n        }\n        return this;\n    }\n\n    @Override\n    public HistoricProcessInstanceQuery processInstanceCallbackIds(Set<String> callbackIds) {\n        if (callbackIds == null || callbackIds.isEmpty()) {\n            throw new FlowableIllegalArgumentException(\"callbackIds is null or empty\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.callbackIds = callbackIds;\n        } else {\n            this.callbackIds = callbackIds;\n        }\n        return this;\n    }\n    \n    @Override\n    public HistoricProcessInstanceQuery processInstanceCallbackType(String callbackType) {\n        if (inOrStatement) {\n            currentOrQueryObject.callbackType = callbackType;\n        } else {\n            this.callbackType = callbackType;\n        }\n        return this;\n    }","sourceCodeStart":751,"sourceCodeEnd":787,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/HistoricProcessInstanceQueryImpl.java#L751-L787","documentation":"Flowable throws this FlowableIllegalArgumentException from HistoricProcessInstanceQuery.processInstanceCallbackIds(Set<String>) when the callbackIds set is null or empty. Callback id filters require at least one id; the query builder validates this eagerly. The set is stored on the query (or current OR query object).","triggerScenarios":"Calling processInstanceCallbackIds(null) or processInstanceCallbackIds(new HashSet<>()) on a HistoricProcessInstanceQuery.","commonSituations":"Aggregating callback ids from prior job submissions where no jobs were created, yielding an empty set; passing an uninitialized Set field.","solutions":["Ensure the Set is non-null and contains at least one callback id before calling","Skip the processInstanceCallbackIds call when no callback ids exist","Collect ids upstream and validate emptiness before query construction"],"exampleFix":"// before\nquery.processInstanceCallbackIds(callbackIds);\n// after\nif (callbackIds != null && !callbackIds.isEmpty()) {\n    query.processInstanceCallbackIds(callbackIds);\n}","handlingStrategy":"validation","validationCode":"if (callbackIds == null || callbackIds.isEmpty()) {\n    throw new IllegalArgumentException(\"callbackIds must contain at least one id\");\n}","typeGuard":"boolean hasCallbackIds(Set<String> ids) {\n    return ids != null && !ids.isEmpty();\n}","tryCatchPattern":"try {\n    query.processInstanceCallbackIds(callbackIds);\n} catch (FlowableIllegalArgumentException e) {\n    LOG.warn(\"Skipping callback id filter: {}\", e.getMessage());\n}","preventionTips":["Only call processInstanceCallbackIds when at least one id was collected","Skip the call when the id set is empty rather than passing an empty set","Build queries incrementally and apply each filter conditionally"],"tags":["flowable","query-builder","validation","empty-collection"],"backgroundTag":"empty-required-field","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}