{"record":{"id":"83ed3f804b99680c","repo":"flowable/flowable-engine","slug":"batch-has-to-be-provided","errorCode":null,"errorMessage":"batch has to be provided","messagePattern":"batch has to be provided","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-batch-service/src/main/java/org/flowable/batch/service/BatchPartBuilderImpl.java","lineNumber":110,"sourceCode":"            throw new FlowableIllegalArgumentException(\"subScopeId is null\");\n        }\n        this.subScopeId = subScopeId;\n        return this;\n    }\n\n    @Override\n    public BatchPartBuilder scopeType(String scopeType) {\n        if (scopeType == null) {\n            throw new FlowableIllegalArgumentException(\"scopeType is null\");\n        }\n        this.scopeType = scopeType;\n        return this;\n    }\n\n    @Override\n    public BatchPart create() {\n        if (batch == null) {\n            throw new FlowableIllegalArgumentException(\"batch has to be provided\");\n        }\n\n        if (type == null) {\n            throw new FlowableIllegalArgumentException(\"type has to be provided\");\n        }\n        if (commandExecutor != null) {\n            return commandExecutor.execute(commandContext -> createSafe());\n        } else {\n            return createSafe();\n        }\n    }\n\n    protected BatchPart createSafe() {\n        BatchPartEntityManager partEntityManager = batchServiceConfiguration.getBatchPartEntityManager();\n        BatchPartEntity batchPart = partEntityManager.create();\n        batchPart.setBatchId(batch.getId());\n        batchPart.setBatchType(batch.getBatchType());\n        batchPart.setBatchSearchKey(batch.getBatchSearchKey());","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-batch-service/src/main/java/org/flowable/batch/service/BatchPartBuilderImpl.java#L92-L128","documentation":"BatchPartBuilderImpl.create() assembles and persists a batch part, but the batch (BatchPartBuilder.batch(BatchPart)) was never called on the builder, so the field is null. Flowable throws FlowableIllegalArgumentException to fail fast rather than persist a part with no owning batch. The error surfaces immediately when you call create().","triggerScenarios":"Calling BatchPartBuilder.create() without first invoking batch(BatchPart) on the builder obtained from batchServiceConfiguration.getBatchService().createBatchPartBuilder() (or the management API equivalent).","commonSituations":"Building a batch part programmatically where the batch was created in another scope and the reference was lost; copy-pasted builder chains where the batch(...) line was deleted; migration from APIs where the batch id string was passed directly to the builder.","solutions":["Obtain/create the Batch first, then call batch(batchPart) on the builder before create(): builder.batch(batchService.createBatchBuilder()...createBatch() or an existing batch).","If you only have a batch id, look it up via batchService.createBatchQuery().batchId(id).singleResult() and pass the entity.","Verify the builder chain order — fluent calls can be reordered so batch(...) is not silently skipped.","Add a null-check/assert on the Batch reference before building the part."],"exampleFix":"// before\nBatchPart part = batchService.createBatchPartBuilder()\n    .type(\"search\")\n    .create();\n// after\nBatch batch = batchService.createBatchBuilder()\n    .type(\"search\")\n    .searchKey(\"k\")\n    .create();\nBatchPart part = batchService.createBatchPartBuilder()\n    .batch(batch)\n    .type(\"search\")\n    .create();","handlingStrategy":"validation","validationCode":"if (batch == null) {\n    throw new IllegalStateException(\"Batch must be created before building a batch part\");\n}\nBatchPart part = batchService.createBatchPartBuilder()\n    .batch(batch)\n    .type(\"search\")\n    .create();","typeGuard":"boolean hasBatch(org.flowable.batch.api.Batch b) {\n    return b != null && b.getId() != null;\n}","tryCatchPattern":"try {\n    BatchPart part = builder.create();\n} catch (org.flowable.common.engine.api.FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"batch has to be provided\")) {\n        throw new IllegalStateException(\"BatchPartBuilder.batch(...) was not called before create()\", e);\n    }\n    throw e;\n}","preventionTips":["Always start the builder chain by resolving or creating the Batch, then call batch(...) immediately.","Wrap builder construction in a helper method so callers cannot build parts without a batch.","Unit-test the builder chain to assert parts are always created with a non-null batch."],"tags":["flowable","batch","builder","null-check"],"backgroundTag":"missing-required-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"}