flowable/flowable-engine · error · FlowableException

byte array for resource '${resourceName}' is null

Error message

byte array for resource '${resourceName}' is null

What it means

After reading the InputStream, addInputStream checks that the produced byte array is not null and throws FlowableException if it is. IOUtils.toByteArray never returns null on success, so reaching this check indicates an exotic/null-returning stream wrapper or a defensive guard against empty/invalid stream implementations. The resource cannot be added to the DMN deployment without bytes.

Source

Thrown at modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/repository/DmnDeploymentBuilderImpl.java:68

        this.deployment = dmnEngineConfiguration.getDeploymentEntityManager().create();
        this.resourceEntityManager = dmnEngineConfiguration.getResourceEntityManager();
    }

    @Override
    public DmnDeploymentBuilder addInputStream(String resourceName, InputStream inputStream) {
        if (inputStream == null) {
            throw new FlowableException("inputStream for resource '" + resourceName + "' is null");
        }

        byte[] bytes = null;
        try {
            bytes = IOUtils.toByteArray(inputStream);
        } catch (Exception e) {
            throw new FlowableException("could not get byte array from resource '" + resourceName + "'", e);
        }

        if (bytes == null) {
            throw new FlowableException("byte array for resource '" + resourceName + "' is null");
        }

        DmnResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(bytes);
        deployment.addResource(resource);
        return this;
    }

    @Override
    public DmnDeploymentBuilder 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) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Replace the custom/wrapper InputStream with a standard one: new ByteArrayInputStream(byteArray) or FileInputStream/Files.newInputStream.
  2. If you hold the content already, use builder.addInputStream(name, new ByteArrayInputStream(bytes)) after verifying bytes != null.
  3. Check that no test mock is leaking into production code paths; restore the real resource source.
  4. Log/inspect the stream class to find which non-standard implementation returns null and fix its read() contract.

Example fix

// before
InputStream is = myCustomStreamWrapper.getStream(); // returns null bytes
builder.addInputStream("decision.dmn", is);

// after
byte[] bytes = Files.readAllBytes(Paths.get("src/main/resources/decision.dmn"));
builder.addInputStream("decision.dmn", new ByteArrayInputStream(bytes));
Defensive patterns

Strategy: type-guard

Validate before calling

byte[] bytes = readSourceBytes();
if (bytes == null || bytes.length == 0) {
    throw new IllegalArgumentException("Resource content is empty/null: " + resourceName);
}
builder.addInputStream(resourceName, new ByteArrayInputStream(bytes));

Type guard

boolean isValidStream(InputStream is) {
    return is != null && !(is instanceof NullInputStream);
}

Try / catch

try {
    builder.addInputStream(name, is);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("byte array for resource")) {
        // stream implementation returned null bytes; rebuild from a standard stream
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling addInputStream(name, is) with a non-null but degenerate InputStream implementation whose read path yields a null byte array (custom or mocking stream), or a wrapper that returns null content. Practically rare — most real failures hit the earlier 'could not get byte array' error instead.

Common situations: Custom InputStream subclasses or test doubles that violate the InputStream contract; framework-provided stream wrappers returning null bytes; passing a placeholder stream from uninitialized code under test.

Related errors


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