flowable/flowable-engine · error · FlowableIllegalArgumentException
resource '${resource}' doesn't exist
Error message
resource '${resource}' doesn't exist What it means
ResourceStreamSource.getInputStream locates a classpath resource via the given (or default) ClassLoader. When the resource cannot be found, it throws this FlowableIllegalArgumentException, since a stream source pointing at a missing classpath entry is an invalid configuration.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/io/ResourceStreamSource.java:49
public ResourceStreamSource(String resource) {
this.resource = resource;
}
public ResourceStreamSource(String resource, ClassLoader classLoader) {
this.resource = resource;
this.classLoader = classLoader;
}
@Override
public InputStream getInputStream() {
InputStream inputStream = null;
if (classLoader == null) {
inputStream = ReflectUtil.getResourceAsStream(resource);
} else {
inputStream = classLoader.getResourceAsStream(resource);
}
if (inputStream == null) {
throw new FlowableIllegalArgumentException("resource '" + resource + "' doesn't exist");
}
return new BufferedInputStream(inputStream);
}
@Override
public String toString() {
return "Resource[" + resource + "]";
}
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Verify the resource path exists under src/main/resources (or another classpath root) and matches exactly, case included.
- Rebuild/redeploy so the resource is packaged in the artifact (check the jar contents).
- Use ReflectUtil.getResourceAsStream with the correct ClassLoader, or pass an explicit ClassLoader that can see the resource.
- If the resource is optional, check availability first via classLoader.getResource(resource) before constructing the stream source.
Example fix
// before
StreamSource src = new ResourceStreamSource("config/rules.xml");
InputStream in = src.getInputStream();
// after
String res = "config/rules.xml";
if (getClass().getClassLoader().getResource(res) == null) {
throw new IllegalArgumentException("Missing classpath resource: " + res);
}
InputStream in = getClass().getClassLoader().getResourceAsStream(res); Defensive patterns
Strategy: validation
Validate before calling
String res = "config/rules.xml";
if (getClass().getClassLoader().getResource(res) == null) throw new IllegalStateException("Classpath resource missing: " + res); Type guard
boolean resourceExists(String res, ClassLoader cl) { return (cl != null ? cl : Thread.currentThread().getContextClassLoader()).getResource(res) != null; } Try / catch
try { in = streamSource.getInputStream(); } catch (FlowableIllegalArgumentException e) { if (e.getMessage().contains("doesn't exist")) log.error("Missing classpath resource: {}", e.getMessage()); else throw e; } Prevention
- Keep resource files under src/main/resources and reference them by exact classpath path
- Check packaged jar contents when resources vanish after builds
- Verify ClassLoader visibility in app-server/OSGi environments
When it happens
Trigger: Creating a ResourceStreamSource (directly or via configuration expecting a classpath resource) with a resource path that does not exist on the classpath; getInputStream then returns null from classLoader.getResourceAsStream(resource).
Common situations: Typos in the resource path; the file exists on the filesystem but not on the classpath (missing from src/main/resources); resource excluded by build filters; wrong ClassLoader in OSGi/app-server deployments.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Couldn't get file ${filePath}: ${e.getMessage()}
- 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/38da6e11b7d00ca7.
Report an issue: GitHub.