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
- Verify the resource exists on the classpath at the exact path passed to addClasspathResource (check target/classes or inside the built jar).
- Fix the resource path: classpath resources are relative to the classpath root, so use 'org/myapp/process.bpmn20.xml', not a filesystem path.
- Ensure build packaging (Maven/Gradle resources plugin) copies .bpmn/.xml/.dmn files into the artifact.
- If the file may legitimately be absent, resolve it first with getClass().getClassLoader().getResource(name) and fail fast with a clear message.
- 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
- Keep deployment resources under src/main/resources and verify they land in target/classes or the jar.
- Assert resource presence in unit tests before deployment.
- Use the deployment id/URL returned by classpath resolution for diagnostics.
- Enable build resource filtering/inclusion for .bpmn/.dmn/.xml files.
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
- resource '${resource}' not found
- resource '${resource}' not found
- Failed to read resource ${resource}
- text is null
- bytes array is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/870528ab9d1876ce.
Report an issue: GitHub.