flowable/flowable-engine · error · FlowableException

could not get byte array from resource

Error message

could not get byte array from resource '${resourceName}'

What it means

While reading the given resource's InputStream into a byte array with IOUtils.toByteArray, an exception occurred, so DmnDeploymentBuilderImpl.addInputStream wraps it in a FlowableException with this message and the original cause attached. The stream could not be fully read, meaning the resource bytes are unavailable for the deployment.

Solutions

  1. Inspect the wrapped cause (e.getCause()) to see the underlying IOException and fix the source (permissions, network, path).
  2. Always pass a fresh, open InputStream — never a stream that was already read or closed; re-create it from the source before each deploy.
  3. For classpath resources use addClasspathResource(name) so the builder opens the stream itself.
  4. If reading from a file, verify it exists and is readable first, or buffer it fully into byte[] yourself and pass a ByteArrayInputStream.

Example fix

// before: stream already consumed/closed
InputStream is = getClass().getResourceAsStream("decision.dmn");
is.read(); // consumed elsewhere
builder.addInputStream("decision.dmn", is); // throws here

// after: fresh stream per deployment
builder.addClasspathResource("decision.dmn");
Defensive patterns

Strategy: try-catch

Validate before calling

try (InputStream is = Files.newInputStream(path)) {
    is.readAllBytes(); // pre-validate the resource is fully readable
}

Try / catch

try {
    builder.addInputStream(name, is);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("could not get byte array")) {
        Throwable cause = e.getCause(); // inspect underlying IOException
        // re-open a fresh stream and retry once
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling addInputStream(name, is) where the stream throws during read — closed stream (e.g. read once then reused), network/URL stream interrupted, IO errors on an underlying file, or a stream implementation that fails mid-read. addClasspathResource passes through here on such failures.

Common situations: Reusing an already-consumed/closed InputStream from another engine call; reading a resource from an unstable network location; disk or permission problems on the source file; interrupted downloads streamed directly into the deployment builder.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

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

    public DmnDeploymentBuilderImpl() {
        DmnEngineConfiguration dmnEngineConfiguration = CommandContextUtil.getDmnEngineConfiguration();
        this.repositoryService = (DmnRepositoryServiceImpl) dmnEngineConfiguration.getDmnRepositoryService();
        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");

View on GitHub (pinned to d6d39ce1c6)