Skip to content

GlobalArguments CEL expressions fail when factory inputs are omitted — selective evaluation not working #653

@stack72

Description

@stack72

Summary

PR #652 documents that globalArgument expressions are selectively evaluated — inputs not provided should be skipped, with a runtime error only if the method code actually accesses an unresolved globalArgument. However, this doesn't work in practice. CEL expressions referencing unprovided inputs fail at expression evaluation time, before the method code runs.

Steps to Reproduce

  1. Create a factory model with an inputs schema containing multiple fields:
name: prod-private-route
inputs:
  properties:
    instanceName:
      type: string
    routeTableId:
      type: string
    natGatewayId:
      type: string
  required:
    - instanceName
    - routeTableId
    - natGatewayId
globalArguments:
  name: ${{ inputs.instanceName }}
  RouteTableId: ${{ inputs.routeTableId }}
  DestinationCidrBlock: "0.0.0.0/0"
  NatGatewayId: ${{ inputs.natGatewayId }}
  1. Call the delete method providing only instanceName and identifier (the only inputs the delete method implementation actually uses):
- name: delete-private-route-a
  task:
    type: model_method
    modelIdOrName: prod-private-route
    methodName: delete
    inputs:
      instanceName: private-route-a
      identifier: ${{ data.latest("prod-private-route", "private-route-a").attributes.RouteTableId + "|" + ... }}
  1. Expected: routeTableId and natGatewayId globalArgument expressions are skipped since the delete method never accesses context.globalArgs.RouteTableId or context.globalArgs.NatGatewayId.

  2. Actual: Fails immediately with:

Invalid expression: No such key: routeTableId

>    1 | inputs.routeTableId
                ^

Impact

This means factory model delete steps must provide all inputs defined in the model's inputs schema, even when the delete method only needs instanceName (for data keying) and identifier (for the AWS API call). This creates unnecessary coupling — delete workflows must duplicate all create-time parameters.

Expected Behavior

GlobalArgument expressions referencing unprovided inputs should be:

  1. Skipped during evaluation (not resolved)
  2. Only cause a runtime error if the method code accesses the unresolved value via context.globalArgs

This would allow delete workflow steps to provide only instanceName + identifier, making them simpler and less coupled to create-time configuration.

Workaround

Provide all inputs to every delete step, pulling values from stored data or hardcoding create-time values:

inputs:
  instanceName: private-route-a
  routeTableId: ${{ data.latest("prod-private-route", "private-route-a").attributes.RouteTableId }}
  natGatewayId: ${{ data.latest("prod-private-route", "private-route-a").attributes.NatGatewayId }}
  identifier: ${{ ... }}

Environment

Discovered while testing a production VPC workflow with 10 factory models and 21 AWS resources. The documentation in PR #652 describes the selective evaluation behavior, but the runtime doesn't implement it.

Metadata

Metadata

Assignees

Labels

betaIssues required to close out before public betabugSomething isn't working

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions