⚠️ Caveats & Gotchas
A friendly list of things that trip people up. Each item has a one-line workaround where relevant.
-
One verb per step, no inline composition. A step executes exactly one verb. You cannot chain a CEL transform and an HTTP call in the same step. Workaround: add a second step.
-
actionhas noout_var— the worker controls output keys. Whatever keys the worker returns are merged directly intoVariables. If twoactionsteps return overlapping keys, the later step's values overwrite the earlier ones. Workaround: prefix output keys in your worker, or use aset_var/transformstep immediately after to rename them. -
CEL verbs read
Variables, notstep.Inputs.transform,filter,map,switch,while,assert, and similar verbs compile theirexpragainstrun.Variables. If the value you need is in the run's initial inputs and not yet inVariables, it is not automatically visible. Workaround: add aset_varstep at the start of your workflow to promote input values into named variables. -
Embedded
actionsteps need a worker or service mode.saga.InMemory()dispatchesactionsteps to its in-process publisher, which pauses the saga. Without a registered worker goroutine to reply, the run will pause indefinitely. Workaround: useRegisterVerbfor in-process handlers, or runcmd/engine+ a gRPC worker for true worker round-trips. -
💡 Embedded
emit_eventmatches in-process (no broker). The in-processEventEmitterboth wakes runs awaiting the topic (header-subset match) and runs the trigger dispatcher, so matchingrecord_transitiontriggers start new runs — parity with service mode. (Payload-CEL trigger matching beyondrecord_transitionis not implemented in either mode yet.) -
💡 Waits support
timeout_s. Bothwait_for_signalandwait_for_eventaccept an optionaltimeout_s; on timeout the run routes to the step'stimeoutbranch if defined, else tonext. (wait_duration/wait_untilare scheduled waits — their firing is the intended path, so no timeout branch.) -
Cancelling a parallel child re-checks the parent join.
cancelon a child that is a branch of aparalleljoin immediately re-evaluates the parent's join and wakes the parent if it is now satisfied (e.g. the cancelled child was the last non-terminal branch, or aquorumis met). Underjoin_strategy: "all"with other branches still running, the parent correctly stays paused until they finish. For partial completion, usejoin_strategy: "quorum". -
ValidateDefinitionis not auto-called by the REST publish path. The engine providesengine.ValidateDefinition(def)to catch structural problems (missing steps, circular references,parallel-inside-try_catch, excessive nesting depth) before a workflow goes live. The RESTPUT /api/v1/workflowsendpoint does not call it automatically. Workaround: callValidateDefinitionin your CI pipeline or publishing tooling before pushing definitions to production. -
The module path is internal. The Go module is hosted at
github.com/Bugs5382/go-saga-orchestration. It is not published to the public Go module proxy. Workaround: add aGONOSUMCHECK/GONOSUMDB/GOFLAGSdirective in your environment, or vendor the module, per your organisation's private module setup.