flowable/flowable-engine · error · FlowableException
Couldn't get file ${filePath}: ${e.getMessage()}
Error message
Couldn't get file ${filePath}: ${e.getMessage()} What it means
IoUtil.getFile resolves a path through the classloader (ClassLoader.getResource) and converts the URL to a File. Any failure — including a null URL when the resource is missing — is wrapped in FlowableException 'Couldn't get file <path>: <message>'.
Source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/util/IoUtil.java:69
byte[] buffer = new byte[(int) getFile(filePath).length()];
BufferedInputStream inputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(getFile(filePath)));
inputStream.read(buffer);
} catch (Exception e) {
throw new FlowableException("Couldn't read file " + filePath + ": " + e.getMessage());
} finally {
IoUtil.closeSilently(inputStream);
}
return new String(buffer);
}
public static File getFile(String filePath) {
URL url = IoUtil.class.getClassLoader().getResource(filePath);
try {
return new File(url.toURI());
} catch (Exception e) {
throw new FlowableException("Couldn't get file " + filePath + ": " + e.getMessage());
}
}
public static void writeStringToFile(String content, String filePath) {
BufferedOutputStream outputStream = null;
try {
outputStream = new BufferedOutputStream(new FileOutputStream(getFile(filePath)));
outputStream.write(content.getBytes());
outputStream.flush();
} catch (Exception e) {
throw new FlowableException("Couldn't write file " + filePath, e);
} finally {
IoUtil.closeSilently(outputStream);
}
}
/**
* Closes the given stream. The same as calling {@link InputStream#close()}, but errors while closing are silently ignored.View on GitHub (pinned to d6d39ce1c6)
Solutions
- Verify the resource path exists and is on the classpath (check the built jar/war contents)
- Fix typos and ensure the file is under src/main/resources so it is packaged
- For resources inside jars, stream them with getResourceAsStream instead of converting to File
- Call getFile only for resources that unpack to real filesystem files
Example fix
// before
File f = IoUtil.getFile("processes/order.bpmn20.xml");
// after
try (InputStream in = getClass().getClassLoader().getResourceAsStream("processes/order.bpmn20.xml")) {
if (in == null) throw new IllegalStateException("resource missing from classpath");
byte[] bytes = IoUtil.readInputStream(in, "processes/order.bpmn20.xml");
} Defensive patterns
Strategy: try-catch
Validate before calling
if (getClass().getClassLoader().getResource(filePath) == null) {
throw new IllegalStateException("Resource not found on classpath: " + filePath);
} Try / catch
try {
File f = IoUtil.getFile(filePath);
} catch (FlowableException e) {
logger.error("Resource lookup failed for {}: {}", filePath, e.getMessage());
} Prevention
- Verify resources are packaged (list jar contents after build)
- For nested-jar resources (Spring Boot fat jar), use getResourceAsStream, not getFile
- Double-check resource path spelling and directory placement in src/main/resources
When it happens
Trigger: Calling getFile (directly or via readFileAsString/writeStringToFile) with a path that does not exist on the classpath, or a resource inside a jar (URL scheme like jar:file:... that File(...) cannot convert, e.g. URISyntaxException).
Common situations: Typo'd resource path; resource not included in the built artifact (missing from src/main/resources); attempting to access resources inside nested jars in Spring Boot fat jars; running from a packaged WAR.
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}' doesn't exist
- resource '${resource}' not found
- resource '${resource}' not found
- Cannot read default EL properties
- Couldn't read file ${filePath}: ${e.getMessage()}
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/630e20ea1dcf1bf4.
Report an issue: GitHub.