{"record":{"id":"c3c230c5b8cbd2a6","repo":"flowable/flowable-engine","slug":"provided-process-definition-must-have-both-key-and","errorCode":null,"errorMessage":"Provided process definition must have both key and resource name set.","messagePattern":"Provided process definition must have both key and resource name set\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/deployer/ProcessDefinitionDiagramHelper.java","lineNumber":42,"sourceCode":"import org.slf4j.LoggerFactory;\n\n/**\n * Creates diagrams from process definitions.\n */\npublic class ProcessDefinitionDiagramHelper {\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(ProcessDefinitionDiagramHelper.class);\n\n    /**\n     * Generates a diagram resource for a ProcessDefinitionEntity and associated BpmnParse. The returned resource has not yet been persisted, nor attached to the ProcessDefinitionEntity. This requires\n     * that the ProcessDefinitionEntity have its key and resource name already set.\n     * \n     * The caller must determine whether creating a diagram for this process definition is appropriate or not, for example see {@link #shouldCreateDiagram(ProcessDefinitionEntity, DeploymentEntity)}.\n     */\n    public ResourceEntity createDiagramForProcessDefinition(ProcessDefinitionEntity processDefinition, BpmnParse bpmnParse) {\n\n        if (StringUtils.isEmpty(processDefinition.getKey()) || StringUtils.isEmpty(processDefinition.getResourceName())) {\n            throw new IllegalStateException(\"Provided process definition must have both key and resource name set.\");\n        }\n\n        ResourceEntity resource = createResourceEntity();\n        ProcessEngineConfiguration processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();\n        try {\n            byte[] diagramBytes = IoUtil.readInputStream(\n                    processEngineConfiguration.getProcessDiagramGenerator().generateDiagram(bpmnParse.getBpmnModel(), \"png\",\n                            processEngineConfiguration.getActivityFontName(),\n                            processEngineConfiguration.getLabelFontName(),\n                            processEngineConfiguration.getAnnotationFontName(),\n                            processEngineConfiguration.getClassLoader(),processEngineConfiguration.isDrawSequenceFlowNameWithNoLabelDI()),\n                    null);\n            String diagramResourceName = ResourceNameUtil.getProcessDiagramResourceName(\n                    processDefinition.getResourceName(), processDefinition.getKey(), \"png\");\n\n            resource.setName(diagramResourceName);\n            resource.setBytes(diagramBytes);\n            resource.setDeploymentId(processDefinition.getDeploymentId());","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/deployer/ProcessDefinitionDiagramHelper.java#L24-L60","documentation":"ProcessDefinitionDiagramHelper.createDiagramForProcessDefinition generates the PNG diagram resource for a deployed process definition, and requires both the definition's key and resourceName to be set to locate/build the artifact. If either is empty it fails fast with this IllegalStateException.","triggerScenarios":"The diagram-generation deployer step runs (shouldCreateDiagram returned true) for a ProcessDefinitionEntity whose key or resourceName is empty — typically a programmatically constructed or partially initialized definition.","commonSituations":"Custom deployers bypassing the normal BpmnDeployer pipeline; definitions built in tests without a resourceName; lifecycle code calling the helper before parsing assigned the resource name.","solutions":["Ensure the BPMN parse step sets both key (process id) and resourceName before diagram creation","Do not bypass the standard BpmnDeployer/Persister pipeline with custom deployer code","If creating diagrams manually, populate key and resourceName on the entity first","Verify shouldCreateDiagram gating in custom code matches the definition's state"],"exampleFix":"// before\nProcessDefinitionEntity def = ...; // resourceName never set\nhelper.createDiagramForProcessDefinition(def, bpmnParse);\n\n// after\ndef.setResourceName(\"processes/order.bpmn20.xml\");\nhelper.createDiagramForProcessDefinition(def, bpmnParse);","handlingStrategy":"validation","validationCode":"if (StringUtils.isEmpty(processDefinition.getKey()) || StringUtils.isEmpty(processDefinition.getResourceName())) {\n    return null; // skip diagram creation\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Route deployments through the standard BpmnDeployer pipeline","Set key and resourceName on entities before invoking diagram helpers","Gate diagram creation on shouldCreateDiagram as the framework does"],"tags":["deployment","diagram","process-definition","precondition"],"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-14T05:17:10.506Z"}