flowable/flowable-engine · error · FlowableException

Failed to read resource

Error message

Failed to read resource 

What it means

Flowable's DeploymentBuilder.addClasspathResource loads a resource from the classpath and attaches it to a deployment as an input stream. If the classpath resource cannot be found or opened, an IOException is wrapped in a FlowableException with this message. It is the engine telling you the resource name you passed does not resolve to a readable stream.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/repository/DeploymentBuilderImpl.java:85

        }
        byte[] bytes = IoUtil.readInputStream(inputStream, resourceName);
        ResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(bytes);
        deployment.addResource(resource);
        return this;
    }

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

    }

    @Override
    public DeploymentBuilder addString(String resourceName, String text) {
        if (text == null) {
            throw new FlowableIllegalArgumentException("text is null");
        }
        ResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(text.getBytes(StandardCharsets.UTF_8));
        deployment.addResource(resource);
        return this;
    }

    @Override
    public DeploymentBuilder addBytes(String resourceName, byte[] bytes) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Verify the resource exists on the classpath at the exact path passed to addClasspathResource (check target/classes or inside the built jar).
  2. Fix the resource path: classpath resources are relative to the classpath root, so use 'org/myapp/process.bpmn20.xml', not a filesystem path.
  3. Ensure build packaging (Maven/Gradle resources plugin) copies .bpmn/.xml/.dmn files into the artifact.
  4. If the file may legitimately be absent, resolve it first with getClass().getClassLoader().getResource(name) and fail fast with a clear message.
  5. If the resource exists but the stream read fails, check file permissions and that the jar/entry is not corrupted.

Example fix

// before
repositoryService.createDeployment()
    .addClasspathResource("processes/my-process.bpmn20.xml") // FileNotFound at deploy time
    .deploy();
// after
String res = "processes/my-process.bpmn20.xml";
if (getClass().getClassLoader().getResource(res) == null) {
    throw new IllegalStateException("Missing deployment resource: " + res);
}
repositoryService.createDeployment()
    .addClasspathResource(res)
    .deploy();
Defensive patterns

Strategy: validation

Validate before calling

boolean resourceExists(String name) {
    return getClass().getClassLoader().getResource(name) != null;
}
if (!resourceExists("processes/my-process.bpmn20.xml")) throw new IllegalStateException("resource missing");

Type guard

boolean isReadableResource(String name) {
    if (name == null) return false;
    try (InputStream is = getClass().getClassLoader().getResourceAsStream(name)) {
        return is != null;
    } catch (IOException e) { return false; }
}

Try / catch

try {
    repositoryService.createDeployment().addClasspathResource(name).deploy();
} catch (FlowableException e) {
    log.error("Failed to read deployment resource {}: {}", name, e.getMessage());
    throw new DeploymentException(name, e);
}

Prevention

When it happens

Trigger: Calling deploymentBuilder.addClasspathResource("path/to/process.bpmn20.xml") where the path does not exist on the classpath, the file name is misspelled, the resource lives in a package not on the classpath, or the stream opens but readBytesFromInputStream throws IOException while reading it.

Common situations: BPMN/XML/dmn resource not included in the built jar or war; resource placed under src/ instead of src/main/resources; wrong leading slash or package path; fat-jar packaging excludes non-java files; working directory differs between IDE and production so resource loading fails.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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