flowable/flowable-engine · error · FlowableException

<e.getMessage()>

Error message

<e.getMessage()>

What it means

Catch-all in AppDeploymentCollectionResource.uploadDeployment: any exception that is not already a FlowableException is rethrown as a FlowableException whose message is the original exception's message (e.getMessage()). The meaningful detail is usually in the cause and server stack trace, since e.getMessage() can be terse or even null (e.g. from an NPE).

Source

Thrown at modules/flowable-app-engine-rest/src/main/java/org/flowable/app/rest/service/api/repository/AppDeploymentCollectionResource.java:231

            deploymentBuilder.name(fileName);

            if (tenantId != null) {
                deploymentBuilder.tenantId(tenantId);
            }

            if (restApiInterceptor != null) {
                restApiInterceptor.enhanceDeployment(deploymentBuilder);
            }

            AppDeployment deployment = deploymentBuilder.deploy();

            return appRestResponseFactory.createAppDeploymentResponse(deployment);

        } catch (Exception e) {
            if (e instanceof FlowableException) {
                throw (FlowableException) e;
            }
            throw new FlowableException(e.getMessage(), e);
        }
    }
    
    public Map<String, String> splitQueryString(String queryString) {
        if (StringUtils.isEmpty(queryString)) {
            return Collections.emptyMap();
        }
        Map<String, String> queryMap = new HashMap<>();
        for (String param : queryString.split("&")) {
            queryMap.put(StringUtils.substringBefore(param, "="), decode(StringUtils.substringAfter(param, "=")));
        }
        return queryMap;
    }
    
    protected String decode(String string) {
        if (string != null) {
            return URLDecoder.decode(string, StandardCharsets.UTF_8);
        }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Inspect the server log stack trace for the wrapped cause (getCause()).
  2. Ensure the uploaded file is a valid .app or zip of valid app definitions.
  3. Verify DB connectivity and that deploymentName/tenant query params are present and non-empty.
  4. In client code, catch FlowableException and surface both message and cause.

Example fix

// before
throw new FlowableException(e.getMessage(), e); // message may be null
// after
String msg = e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName();
throw new FlowableException("Deployment failed: " + msg, e);
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight checks before deploying
if (StringUtils.isEmpty(deploymentName)) throw new IllegalArgumentException("deploymentName required");
if (!file.canRead()) throw new IllegalArgumentException("uploaded file unreadable");

Try / catch

try {
    return uploadDeployment(request, tenantId);
} catch (FlowableException e) {
    throw e; // server already classified it
} catch (Exception e) {
    throw new FlowableException("Deployment failed: " + e, e); // include full exception; message may be null
}

Prevention

When it happens

Trigger: Any non-Flowable failure during deployment build/save: repository save errors, IO problems reading the uploaded file, NPEs from missing query params, resource conversion errors inside the deployment builder.

Common situations: DB connection failures during repositoryService.createDeployment().deploy(); invalid .app/zip content rejected by the underlying engine with a non-Flowable exception; NullPointerException whose message is null, producing a confusing empty message.

Related errors


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