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

  1. Verify the resource path exists under src/main/resources (or another classpath root) and matches exactly, case included.
  2. Rebuild/redeploy so the resource is packaged in the artifact (check the jar contents).
  3. Use ReflectUtil.getResourceAsStream with the correct ClassLoader, or pass an explicit ClassLoader that can see the resource.
  4. 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

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


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