flowable/flowable-engine · error · FlowableException

resource '${resource}' not found

Error message

resource '${resource}' not found

What it means

addClasspathResource() looks up the given resource on the classloader; when getResourceAsStream returns null the resource does not exist on the classpath, and the builder throws FlowableException("resource '...' not found"). This is the standard 'file not on classpath' failure when deploying app archives programmatically.

Source

Thrown at modules/flowable-app-engine/src/main/java/org/flowable/app/engine/impl/repository/AppDeploymentBuilderImpl.java:76

            throw new FlowableException("could not get byte array from resource '" + resourceName + "'", e);
        }

        if (bytes == null) {
            throw new FlowableException("byte array for resource '" + resourceName + "' is null");
        }

        AppResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(bytes);
        deployment.addResource(resource);
        return this;
    }

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

    @Override
    public AppDeploymentBuilder addString(String resourceName, String text) {
        if (text == null) {
            throw new FlowableException("text is null");
        }

        AppResourceEntity resource = resourceEntityManager.create();
        resource.setName(resourceName);
        resource.setBytes(text.getBytes(StandardCharsets.UTF_8));

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Check the exact classpath-relative path and spelling; getResourceAsStream is case-sensitive and root-relative.
  2. Move the file into src/main/resources (or the equivalent source set) and rebuild so it is packaged.
  3. Verify packaging: open the built jar/war and confirm the resource is present at the expected path.
  4. Check Maven resource filtering/exclusions or Gradle processResources config aren't excluding the file.
  5. Confirm existence first with getClass().getClassLoader().getResource(resource) before deploying.

Example fix

// before
deploymentBuilder.addClasspathResource("MyApp.bar"); // actual path: apps/myApp.bar

// after
deploymentBuilder.addClasspathResource("apps/myApp.bar");
Defensive patterns

Strategy: validation

Validate before calling

if (getClass().getClassLoader().getResource(resource) == null) { throw new IllegalStateException("Classpath resource not found: " + resource); }

Try / catch

try { deploymentBuilder.addClasspathResource(resource); } catch (FlowableException e) { log.error("Resource {} missing from classpath; check packaging", resource); }

Prevention

When it happens

Trigger: deploymentBuilder.addClasspathResource("myApp.bar") where the name is misspelled, lacks the correct path prefix (e.g. needs 'app/myApp.bar'), differs in case, or the file was not packaged into the jar/war.

Common situations: Resource placed outside src/main/resources so it never lands in the artifact; typos or absolute filesystem paths passed instead of classpath-relative names; case-sensitive filesystems vs. case-insensitive dev machines; resources filtered out by Maven/Gradle resource config.

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/b6ed229d2e16a7b9. Report an issue: GitHub.