flowable/flowable-engine · error · FlowableIllegalArgumentException

Transient variable name is required

Error message

Transient variable name is required

What it means

Transient variables supplied when completing a task must each carry a name; an unnamed transient RestVariable triggers FlowableIllegalArgumentException (HTTP 400). Transient variables are not persisted, but they still need an identifier to be passed through the completion builder.

Solutions

  1. Set the name field on every transientVariables entry.
  2. Validate the payload before sending.
  3. Fix DTO/serializer mapping that loses the name for transient variables.
  4. Drop transient variables that have no meaningful name and pass them differently.

Example fix

// before
{"action":"complete","transientVariables":[{"value":42}]}

// after
{"action":"complete","transientVariables":[{"name":"tmpCount","value":42}]}
Defensive patterns

Strategy: validation

Validate before calling

transientVars.forEach(v => { if (!v.name) throw new Error('transient variable missing name'); });

Type guard

const valid = tvs.filter(v => typeof v.name === 'string' && v.name.length > 0);

Try / catch

try { await api.post(`/cmmn-runtime/tasks/${id}`, body); } catch (e) { if (e.response && e.response.status === 400) { /* repair transientVariables payload */ } throw e; }

Prevention

When it happens

Trigger: POST /cmmn-runtime/tasks/{taskId} with action 'complete' and a transientVariables array containing an element whose name is null or missing.

Common situations: Constructing transient variable maps programmatically where the key wasn't copied into the RestVariable.name field; JSON payloads omitting name for transient entries.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — 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/20783a3cb80f1fe1. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskResource.java:222

            for (RestVariable var : actionRequest.getVariables()) {
                if (var.getName() == null) {
                    throw new FlowableIllegalArgumentException("Variable name is required");
                }

                Object actualVariableValue = restResponseFactory.getVariableValue(var);
                if (var.getVariableScope() != null && RestVariable.RestVariableScope.LOCAL.equals(var.getVariableScope())) {
                    taskCompletionBuilder.variableLocal(var.getName(), actualVariableValue);
                } else {
                    taskCompletionBuilder.variable(var.getName(), actualVariableValue);
                }

            }
        }

        if (actionRequest.getTransientVariables() != null) {
            for (RestVariable var : actionRequest.getTransientVariables()) {
                if (var.getName() == null) {
                    throw new FlowableIllegalArgumentException("Transient variable name is required");
                }

                Object actualVariableValue = restResponseFactory.getVariableValue(var);
                if (var.getVariableScope() != null && RestVariable.RestVariableScope.LOCAL.equals(var.getVariableScope())) {
                    taskCompletionBuilder.transientVariableLocal(var.getName(), actualVariableValue);
                } else {
                    taskCompletionBuilder.transientVariable(var.getName(), actualVariableValue);
                }
            }
        }

        taskCompletionBuilder
                .taskId(task.getId())
                .formDefinitionId(actionRequest.getFormDefinitionId())
                .outcome(actionRequest.getOutcome())
                .complete();
    }

View on GitHub (pinned to d6d39ce1c6)