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

#294 forEach self.* in modelIdOrName not resolved in runtime execution path

Opened by webframp Ā· 5/8/2026Ā· Shipped 5/8/2026

Description

Commit 5a0b2cbc (swamp-club#279, PR #1334) added self.* resolution in modelIdOrName to resolveForEachTaskExpressions() in src/libswamp/workflows/evaluate.ts. This correctly resolves during swamp workflow evaluate display output, but the runtime execution path still passes the raw ${{ self.region }} string to findDefinitionByIdOrName(), causing "Model not found" errors.

Steps to Reproduce

# Workflow with forEach targeting dynamic model names
steps:
  - name: summary-${{ self.region }}
    forEach:
      item: region
      in: ${{ inputs.regions }}
    task:
      type: model_method
      modelIdOrName: aws-alarms-${{ self.region }}
      methodName: get_summary
      inputs:
        historyHours: 24
    allowFailure: true
# Model instances exist
swamp model create @webframp/aws/alarms aws-alarms-us-east-1 --global-arg region=us-east-1

# Run directly — fails
swamp workflow run morning-pulse --input 'regions:json=["us-east-1"]'
# Error: Model not found: aws-alarms-${{ self.region }}

# Evaluate shows correct resolution in display output
swamp workflow evaluate morning-pulse --input 'regions:json=["us-east-1"]' --json | grep modelIdOrName
# "modelIdOrName": "aws-alarms-us-east-1"  ← correct

# But evaluated file still has raw expression
grep modelIdOrName .swamp/workflows-evaluated/workflow-*.yaml
# modelIdOrName: 'aws-alarms-${{ self.region }}'  ← not persisted

# --last-evaluated also fails (file has unexpanded forEach)
swamp workflow run morning-pulse --last-evaluated
# Error: Model not found: aws-alarms-${{ self.region }}

Root Cause

Two gaps remain after swamp-club#279:

  1. Runtime path not patched: expandForEachSteps() in src/domain/workflows/execution_service.ts creates the forEachVar context and resolves step names, but passes the original step object (with unresolved modelIdOrName) to execution. The resolveForEachTaskExpressions() fix only runs in the evaluate display codepath (src/libswamp/workflows/evaluate.ts), not in the runtime codepath.

  2. Evaluated file doesn't persist forEach expansion: swamp workflow evaluate saves the workflow YAML with forEach blocks intact and self.* still in modelIdOrName. The expansion shown in the JSON output is display-only. This means --last-evaluated can't work around the runtime gap.

Expected Behavior

swamp workflow run morning-pulse --input 'regions:json=["us-east-1"]' should resolve aws-alarms-${{ self.region }} to aws-alarms-us-east-1 during runtime forEach expansion, matching the behavior shown in swamp workflow evaluate output.

Environment

  • swamp version: 20260507.205536.0-sha.10d12371
  • OS: Linux

References

02Bog Flow
āœ“OPENāœ“TRIAGEDāœ“IN PROGRESSāœ“SHIPPED+ 1 MOREASSIGNED+ 7 MOREREVIEW+ 3 MOREPR_MERGEDSHIPPED

Shipped

5/8/2026, 12:50:20 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack725/8/2026, 11:55:48 AM

Sign in to post a ripple.