flowable/flowable-engine · error · FlowableException

text is null

Error message

text is null

What it means

FlowableException thrown by EventDeploymentBuilderImpl.addString when the text argument is null. addString stores an in-memory string resource (e.g. an event or channel XML definition) as UTF-8 bytes in the deployment, which cannot hold a null payload.

Solutions

  1. Ensure the definition string is non-null before calling addString.
  2. Check the source of the text (config, env var, file) and provide a default.
  3. If the resource is byte-based, use addEventDefinitionBytes/addChannelDefinitionBytes with valid bytes instead.

Example fix

// before
String xml = config.get("order.event.xml");
builder.addString("order.event", xml);
// after
String xml = config.getOrDefault("order.event.xml", DEFAULT_ORDER_EVENT_XML);
Objects.requireNonNull(xml, "order event xml must be set");
builder.addString("order.event", xml);
Defensive patterns

Strategy: validation

Validate before calling

if (text == null || text.isEmpty()) { throw new IllegalArgumentException("definition text for " + resourceName + " must be non-empty"); }

Type guard

boolean ok = text instanceof String s && !s.isEmpty();

Try / catch

try { builder.addString(name, text); } catch (FlowableException e) { LOG.error("null definition text for " + name); throw e; }

Prevention

When it happens

Trigger: Calling deploymentBuilder.addString(resourceName, text) with text == null; e.g. passing a null String returned from a config lookup or template renderer.

Common situations: XML definition loaded from a property/environment variable that is unset; a template engine returning null; refactored code that lost a default value.

Related errors


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

Appendix: source

Thrown at modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/repository/EventDeploymentBuilderImpl.java:91

    }

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

    @Override
    public EventDeploymentBuilder addString(String resourceName, String text) {
        if (text == null) {
            throw new FlowableException("text is null");
        }

        EventResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(text.getBytes(StandardCharsets.UTF_8));
        deployment.addResource(resource);
        return this;
    }

    @Override
    public EventDeploymentBuilder addEventDefinitionBytes(String resourceName, byte[] eventDefinitionBytes) {
        if (eventDefinitionBytes == null) {
            throw new FlowableException("event definition bytes is null");
        }

        EventResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(eventDefinitionBytes);

View on GitHub (pinned to d6d39ce1c6)