flowable/flowable-engine · error · FlowableIllegalArgumentException

Error code must not be empty.

Error message

Error code must not be empty.

What it means

BusinessError.setErrorCode throws FlowableIllegalArgumentException("Error code must not be empty.") when a BusinessError is constructed with an empty-string error code. The error code must be a non-null, non-empty string to be usable in error-boundary/bpmn error matching.

Source

Thrown at modules/flowable-engine-common-api/src/main/java/org/flowable/common/engine/api/delegate/BusinessError.java:58

        setErrorCode(errorCode);
    }

    protected BusinessError(String errorCode, String message) {
        super(message);
        setErrorCode(errorCode);
    }

    protected BusinessError(String errorCode, String message, Throwable cause) {
        super(message, cause);
        setErrorCode(errorCode);
    }

    protected void setErrorCode(String errorCode) {
        if (errorCode == null) {
            throw new FlowableIllegalArgumentException("Error code must not be null.");
        }
        if (errorCode.isEmpty()) {
            throw new FlowableIllegalArgumentException("Error code must not be empty.");
        }
        this.errorCode = errorCode;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public VariableContainer getAdditionalDataContainer() {
        return additionalDataContainer;
    }

    public void setAdditionalDataContainer(VariableContainer additionalDataContainer) {
        this.additionalDataContainer = additionalDataContainer;
    }

    public abstract void addAdditionalData(String name, Object value);
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a meaningful non-empty error code string when constructing the BusinessError
  2. Validate/trim and default the code before construction: if (code == null || code.isBlank()) code = "DEFAULT";
  3. Check the source (config/variable) of the code for blank values and fix the upstream data

Example fix

// before
String code = config.get("businessErrorCode"); // may be ""
throw new BusinessError(code, null);
// after
String code = config.getOrDefault("businessErrorCode", "DEFAULT").trim();
if (code.isEmpty()) { code = "DEFAULT"; }
throw new BusinessError(code, null);
Defensive patterns

Strategy: validation

Validate before calling

// guard before constructing a BusinessError
String trimmed = errorCode == null ? null : errorCode.trim();
if (trimmed == null || trimmed.isEmpty()) {
    throw new IllegalArgumentException("Business error code must be non-empty");
}

Try / catch

try {
    throw new BusinessError(code, cause);
} catch (FlowableIllegalArgumentException e) {
    LOGGER.error("Invalid business error code: {}", e.getMessage());
    throw new BusinessError("DEFAULT_BUSINESS_ERROR", cause);
}

Prevention

When it happens

Trigger: Invoking a BusinessError constructor with "" as errorCode, or a subclass calling setErrorCode("").

Common situations: Error codes read from configuration files or process variables that are present but empty, trimmed strings that end up as "", or template-generated code values that were left blank.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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