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
- If referencing an existing workflow, use the 'name' (and optional 'version') field, not workflowDefinition.
- If supplying an inline definition, pass it as a JSON object (LinkedHashMap/WorkflowDef), not a string.
- 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
- Use the 'name'/'version' fields to reference registered sub-workflows.
- Pass inline definitions as objects, not strings.
- Validate workflowDefinition shape at the API boundary.
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
- workflowDefinition must be either null, or WorkflowDef, or a
- Invalid skill manifest JSON: {e.getMessage()}
- priority MUST be between 0 and 99 (inclusive)
- Model string cannot be null or empty
- Invalid model format: '%s'. Expected 'provider/model'.
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/1c537e07a5759c28.
Report an issue: GitHub.