conductor-oss/conductor · error · IllegalArgumentException

workflowDefinition is a string, but not a valid DSL string

Error message

workflowDefinition is a string, but not a valid DSL string

What it means

SubWorkflowParams.setWorkflowDefinition accepts a String only when it is a DSL expression wrapped in '${...}'. This error fires when the supplied string does not both start with '${' and end with '}' - i.e. it is not a recognized DSL expression. Literal workflow names or raw JSON passed as a string hit this path.

Source

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

    @Deprecated
    @JsonIgnore
    public WorkflowDef getWorkflowDef() {
        return (WorkflowDef) workflowDefinition;
    }

    /**
     * @param workflowDef the workflowDefinition to set
     */
    @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()) {

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. If referencing an existing workflow, use the 'name' (and optional 'version') field, not workflowDefinition.
  2. If supplying an inline definition, pass it as a JSON object (LinkedHashMap/WorkflowDef), not a string.
  3. If using a DSL expression, ensure it is wrapped as ${...}.

Example fix

// before: plain string - rejected
{"subWorkflowParam": {"workflowDefinition": "myWorkflow"}}

// after: reference by name instead
{"subWorkflowParam": {"name": "myWorkflow", "version": 1}}
// or inline object:
{"subWorkflowParam": {"workflowDefinition": {"name": "myWorkflow", "version": 1}}}
Defensive patterns

Strategy: validation

Validate before calling

// Validate a DSL string before setting workflowDefinition
static boolean isValidDslString(Object v) {
    return v instanceof String s && s.startsWith("${") && s.endsWith("}");
}
// use the 'name' field for references, or an object for inline defs

Type guard

// Narrow a workflowDefinition value to its valid forms
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 malformed workflowDefinition and report clearly
try {
    params.setWorkflowDefinition(raw);
} catch (IllegalArgumentException e) {
    throw new BadRequestException(
        "workflowDefinition must be null, a WorkflowDef, an object, or a ${...} DSL string", e);
}

Prevention

When it happens

Trigger: Setting the JSON field 'workflowDefinition' to a plain string that lacks the leading '${' or trailing '}' (e.g. "myWorkflow" or "{\"name\":...}" as a String).

Common situations: Confusing the 'name' field (a registered sub-workflow reference) with 'workflowDefinition'; sending a serialized WorkflowDef JSON as a string instead of an object; passing a non-DSL template string.

Related errors


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