Skip to main content
← Back to list
01Issue
BugShippedSwamp CLI
Assigneesstack72

Relationships

#1334 forEach leaves self.* unresolved in target

Opened by ehazlett · 7/22/2026· Shipped 7/22/2026

Using forEach to create one workflow step per worker does not resolve the iteration value inside the step-level target field.

Tested with:

swamp 20260722.020746.0-sha.5d00afa2

Minimal example:

id: aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaa10
name: dynamic-worker-targeting
inputs:
  properties: {}

jobs:
  - name: collect
    steps:
      - name: collect-${{ self.worker.attributes.name }}
        forEach:
          item: worker
          in: ${{ data.query('modelType == "swamp/worker"') }}

        target: ${{ self.worker.attributes.name }}

        task:
          type: model_method
          modelIdOrName: host-inventory
          methodName: sync

        dependsOn: []
        weight: 0

    dependsOn: []
    weight: 0

version: 1

Run:

swamp workflow evaluate dynamic-worker-targeting \
  --repo-dir /path/to/repository \
  --json

The evaluator expands the step name correctly:

{
  "name": "collect-worker-01",
  "target": "${{ self.worker.attributes.name }}"
}

The same self.worker.attributes.name expression is therefore resolved in name but left as literal text in target.

When the workflow is executed through swamp serve, dispatch waits for a worker whose target is literally:

${{ self.worker.attributes.name }}

The workflow then remains queued until queueTimeout expires. The resulting dispatch error does not identify the unresolved expression.

Expected behavior

Each expanded step should use its corresponding worker name:

{
  "name": "collect-worker-01",
  "target": "worker-01"
}

Placement fields such as target, labels, and platform should resolve self.* during forEach expansion, consistently with other step fields.

At minimum, validation should reject unresolved ${{ ... }} expressions in placement fields. Treating an unresolved expression as a literal placement constraint leads to a delayed timeout instead of an actionable validation error.

Impact

This prevents the direct expression of a common fleet operation: create one step per worker and pin each step to that worker.

Without per-instance targeting, multiple expanded steps may execute on the same eligible worker while other workers are missed. The workaround is to introduce a child workflow, pass the worker name as an input, and use ${{ inputs.workerName }} as the child’s target.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 4 MOREPR_MERGED+ 1 MORECONTRIBUTOR_NOTIFIED

Shipped

7/22/2026, 6:31:07 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack727/22/2026, 5:33:02 PM
Editable. Press Enter to edit.

stack72 commented 7/22/2026, 6:31:15 PM

Thanks @ehazlett for reporting this! The fix has been merged and a release is on its way. We appreciate your contribution to swamp.

Sign in to post a ripple.