flowable/flowable-engine · error · FlowableException

Failed to read resource

Error message

Failed to read resource ${resource}

What it means

FlowableException thrown by EventDeploymentBuilderImpl.addClasspathResource when reading a classpath resource fails with an IOException (or the resource stream cannot be processed) during deployment resource loading. The builder loads classpath resources as event/channel definition files into the deployment. The causing IOException is attached as the cause.

Solutions

  1. Verify the classpath resource exists via getClass().getResourceAsStream(resource) before calling addClasspathResource.
  2. Check that the underlying file/JAR is readable and not corrupted.
  3. Inspect the wrapped IOException cause for the actual read failure.
  4. If the resource is missing, note the distinct 'resource not found' FlowableException path and fix the resource path/name.

Example fix

// before
deploymentBuilder.addClasspathResource("events/order.event");
// after
try (InputStream is = getClass().getClassLoader().getResourceAsStream("events/order.event")) {
    if (is != null) {
        deploymentBuilder.addInputStream("events/order.event", is);
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (getClass().getClassLoader().getResource(resource) == null) { throw new IllegalArgumentException("classpath resource missing: " + resource); }

Type guard

boolean exists = getClass().getClassLoader().getResource(resource) != null;

Try / catch

try { builder.addClasspathResource(resource); } catch (FlowableException e) { LOG.error("failed reading deployment resource " + resource, e.getCause()); throw e; }

Prevention

When it happens

Trigger: Calling EventDeploymentBuilder.addClasspathResource(resource) where the resource exists but reading its InputStream throws IOException (e.g. stream already consumed, broken classloader/JAR).

Common situations: Deploying event definitions from a JAR with a corrupted or closed stream; resources inside an executable JAR accessed via FileInputStream-style assumptions; classloader quirks in app servers.

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/d747536b1a43b562. Report an issue: GitHub.

Appendix: source

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

        }

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

    @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) {

View on GitHub (pinned to d6d39ce1c6)