flowable/flowable-engine · error · FlowableException

text is null

Error message

text is null

What it means

Flowable's AppDeploymentBuilder.addString() throws this FlowableException when the caller passes a null text payload for a resource. The builder refuses to create an AppResourceEntity with no content, since deployments require byte content for every resource.

Source

Thrown at modules/flowable-app-engine/src/main/java/org/flowable/app/engine/impl/repository/AppDeploymentBuilderImpl.java:89

    @Override
    public AppDeploymentBuilder 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 AppDeploymentBuilder addString(String resourceName, String text) {
        if (text == null) {
            throw new FlowableException("text is null");
        }

        AppResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(text.getBytes(StandardCharsets.UTF_8));
        deployment.addResource(resource);
        return this;
    }
    
    @Override
    public AppDeploymentBuilder addBytes(String resourceName, byte[] bytes) {
        if (bytes == null) {
            throw new FlowableException("bytes array is null");
        }

        AppResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(bytes);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure the text variable is non-null before calling addString (initialize or fail fast with a check).
  2. If content may be absent, skip addString entirely instead of passing null.
  3. Use addBytes with a non-null byte[] if you already have raw bytes.
  4. Catch FlowableException around the builder chain and log which resourceName had null text.

Example fix

// before
builder.addString("my-app.app.xml", appXml); // appXml may be null
// after
if (appXml != null) {
    builder.addString("my-app.app.xml", appXml);
} else {
    throw new IllegalStateException("app definition content missing");
}
Defensive patterns

Strategy: validation

Validate before calling

if (text == null) { throw new IllegalArgumentException("text must not be null for resource " + resourceName); }

Type guard

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

Try / catch

try {
    builder.addString(resourceName, text);
} catch (org.flowable.common.engine.api.FlowableException e) {
    logger.error("Failed to add resource {}: {}", resourceName, e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: Calling appRepositoryService.createDeployment().addString(resourceName, null) — the text argument is null at the moment of the call.

Common situations: Dynamically generated XML/JSON app definition assembled into a variable that was never initialized, or a lookup (config value, template read) that returned null and was passed straight through.

Related errors


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