flowable/flowable-engine · error · FlowableIllegalArgumentException

text is null

Error message

text is null

What it means

Flowable's DeploymentBuilder.addString attaches an in-memory String as a deployment resource. The API rejects a null text argument with a FlowableIllegalArgumentException because a resource with no content cannot be stored. The content may be null because the caller passed a null literal or an unresolved variable.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/repository/DeploymentBuilderImpl.java:93

    @Override
    public DeploymentBuilder addClasspathResource(String resource) {
        try (final InputStream inputStream = ReflectUtil.getResourceAsStream(resource)) {
	        if (inputStream == null) {
	            throw new FlowableIllegalArgumentException("resource '" + resource + "' not found");
	        }
	        return addInputStream(resource, inputStream);
	        
        } catch (IOException ex) {
            throw new FlowableException("Failed to read resource " + resource, ex);
        }

    }

    @Override
    public DeploymentBuilder addString(String resourceName, String text) {
        if (text == null) {
            throw new FlowableIllegalArgumentException("text is null");
        }
        ResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(text.getBytes(StandardCharsets.UTF_8));
        deployment.addResource(resource);
        return this;
    }

    @Override
    public DeploymentBuilder addBytes(String resourceName, byte[] bytes) {
        if (bytes == null) {
            throw new FlowableIllegalArgumentException("bytes is null");
        }
        ResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(bytes);

        deployment.addResource(resource);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure the String passed to addString is non-null before calling; check the variable that produces it.
  2. If using addBpmnModel, verify the BpmnModel contains at least one process so XML conversion yields content.
  3. Use addString(resourceName, text == null ? "" : text) only if an empty resource is acceptable; otherwise treat null as a bug.
  4. Log the resource name and producer of the text to find where null originates.

Example fix

// before
String bpmnXml = config.getBpmnXml(); // may be null
repositoryService.createDeployment().addString("proc.bpmn20.xml", bpmnXml).deploy();
// after
String bpmnXml = config.getBpmnXml();
if (bpmnXml == null || bpmnXml.isEmpty()) {
    throw new IllegalStateException("bpmnXml is not configured");
}
repositoryService.createDeployment().addString("proc.bpmn20.xml", bpmnXml).deploy();
Defensive patterns

Strategy: validation

Validate before calling

if (text == null || text.isEmpty()) throw new IllegalArgumentException("resource text for " + resourceName + " is empty");

Type guard

boolean hasText(String s) { return s != null && !s.trim().isEmpty(); }

Try / catch

try {
    builder.addString(name, text).deploy();
} catch (FlowableIllegalArgumentException e) {
    log.error("addString rejected input: {}", e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: Calling deploymentBuilder.addString(resourceName, null); addBpmnModel internally converts the model to XML and calls addString, so a model that serializes to null text also triggers it; passing a String variable that was never initialized.

Common situations: Programmatic model creation where BpmnModel conversion produced no output; refactoring that removed the string constant; configuration property expected to hold the XML but was null; NPE-avoiding wrappers that pass null through.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/3dbb0d6a75fc645a. Report an issue: GitHub.