flowable/flowable-engine · error · FlowableIllegalArgumentException

invalid: multiple sources " + this.streamSource + " and " +

Error message

invalid: multiple sources " + this.streamSource + " and " + streamSource

What it means

A single BpmnParse instance can only have one stream source (input stream, URL, resource, or string). setStreamSource throws FlowableIllegalArgumentException if a second source is set on a BpmnParse that already has one, since the parser would not know which content to parse.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/parser/BpmnParse.java:264

    public BpmnParse sourceResource(String resource, ClassLoader classLoader) {
        if (name == null) {
            name(resource);
        }
        setStreamSource(new ResourceStreamSource(resource, classLoader));
        return this;
    }

    public BpmnParse sourceString(String string) {
        if (name == null) {
            name("string");
        }
        setStreamSource(new StringStreamSource(string));
        return this;
    }

    protected void setStreamSource(StreamSource streamSource) {
        if (this.streamSource != null) {
            throw new FlowableIllegalArgumentException("invalid: multiple sources " + this.streamSource + " and " + streamSource);
        }
        this.streamSource = streamSource;
    }

    public BpmnParse setSourceSystemId(String sourceSystemId) {
        this.sourceSystemId = sourceSystemId;
        return this;
    }

    /**
     * Parses the 'definitions' root element
     */
    protected void applyParseHandlers() {
        sequenceFlows = new HashMap<>();
        for (Process process : bpmnModel.getProcesses()) {
            currentProcess = process;
            if (process.isExecutable()) {
                bpmnParserHandlers.parseElement(this, process);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Create a new BpmnParse per process definition (repositoryService.createDeployment() handles this per resource)
  2. Reset or discard the BpmnParse instance before setting a new source
  3. If you need to switch sources, build a fresh parse: processEngineConfiguration.getBpmnParseFactory().createBpmnParse(...)

Example fix

// before
BpmnParse parse = bpmnParseFactory.createBpmnParse();
parse.sourceResource("a.bpmn").sourceResource("b.bpmn").execute(); // throws
// after
BpmnParse parse = bpmnParseFactory.createBpmnParse();
parse.sourceResource("b.bpmn").execute();
Defensive patterns

Strategy: validation

Validate before calling

if (parse.hasStreamSource()) { /* create new BpmnParse */ } // or simply always create a fresh BpmnParse per resource

Try / catch

try {
    parse.sourceInputStream(is);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().startsWith("invalid: multiple sources")) {
        parse = bpmnParseFactory.createBpmnParse();
    }
}

Prevention

When it happens

Trigger: Reusing the same BpmnParse object and calling sourceInputStream/sourceUrl/sourceResource/sourceString twice, or chaining two source* setters on one instance.

Common situations: Loop that parses multiple resources but forgot to create a fresh BpmnParse per resource; copy-pasted parsing code accidentally setting source twice.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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