conductor-oss/conductor · error · IllegalArgumentException

workflowDefinition must be either null, or WorkflowDef, or a

Error message

workflowDefinition must be either null, or WorkflowDef, or a valid DSL string

What it means

SubWorkflowParams.setWorkflowDefinition only accepts null, a WorkflowDef, a '${...}' DSL String, or a LinkedHashMap (converted to a WorkflowDef). Any other runtime type - number, boolean, plain HashMap, array/List - reaches the final else branch and throws this IllegalArgumentException.

Source

Thrown at common/src/main/java/com/netflix/conductor/common/metadata/workflow/SubWorkflowParams.java:167

     */
    @JsonSetter("workflowDefinition")
    public void setWorkflowDefinition(Object workflowDef) {
        if (workflowDef == null) {
            this.workflowDefinition = workflowDef;
        } else if (workflowDef instanceof WorkflowDef) {
            this.workflowDefinition = workflowDef;
        } else if (workflowDef instanceof String) {
            if (!(((String) workflowDef).startsWith("${"))
                    || !(((String) workflowDef).endsWith("}"))) {
                throw new IllegalArgumentException(
                        "workflowDefinition is a string, but not a valid DSL string");
            } else {
                this.workflowDefinition = workflowDef;
            }
        } else if (workflowDef instanceof LinkedHashMap) {
            this.workflowDefinition = TaskUtils.convertToWorkflowDef(workflowDef);
        } else {
            throw new IllegalArgumentException(
                    "workflowDefinition must be either null, or WorkflowDef, or a valid DSL string");
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        SubWorkflowParams that = (SubWorkflowParams) o;
        return Objects.equals(getName(), that.getName())
                && Objects.equals(getVersion(), that.getVersion())
                && Objects.equals(getTaskToDomain(), that.getTaskToDomain())
                && Objects.equals(getWorkflowDefinition(), that.getWorkflowDefinition())
                && Objects.equals(idempotencyKey, that.idempotencyKey)

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Send workflowDefinition as a JSON object that deserializes to a WorkflowDef/LinkedHashMap.
  2. Omit the field (null) when you only need the sub-workflow name.
  3. Validate the payload type before submission - only object, string, or null are valid.

Example fix

// before: scalar/array - rejected
{"subWorkflowParam": {"workflowDefinition": 1}}

// after: object form
{"subWorkflowParam": {"workflowDefinition": {"name": "myWorkflow", "version": 1}}}
Defensive patterns

Strategy: type-guard

Validate before calling

// Only allow object/string/null through to setWorkflowDefinition
static boolean isAcceptableWorkflowDefinitionType(Object v) {
    if (v == null) return true;
    return v instanceof WorkflowDef || v instanceof LinkedHashMap || v instanceof String;
}

Type guard

// Type-guard: accept only the supported runtime types
static boolean isValidWorkflowDefinition(Object v) {
    if (v == null) return true;
    if (v instanceof WorkflowDef) return true;
    if (v instanceof LinkedHashMap) return true;
    return v instanceof String s && s.startsWith("${") && s.endsWith("}");
}

Try / catch

// Catch the type error and reject the payload with context
try {
    params.setWorkflowDefinition(raw);
} catch (IllegalArgumentException e) {
    throw new BadRequestException(
        "workflowDefinition has unsupported type: " + raw.getClass(), e);
}

Prevention

When it happens

Trigger: Sending the 'workflowDefinition' JSON field as a scalar (int/boolean), an array, or a non-LinkedHashMap map type that Jackson deserializes to something other than LinkedHashMap.

Common situations: A client serializing the field incorrectly (e.g. a JSON number or array); passing a HashMap that Jackson maps to a different concrete type; malformed API payload from a generated SDK.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/c0381ecc108f6bfb. Report an issue: GitHub.