Skip to Content
Evaluate Get Started

Direct State Control

A process instance can get stuck. A command may be unavailable because its condition is no longer met. A transition may reference a deleted action. An error handler may loop without advancing. Without a way to manually reposition the instance, the only option is to delete it and start over.

Direct state control lets you move a process instance to a target activity directly, bypassing the normal command execution pipeline. You specify the target state, and the runtime places the instance there without selecting a configured transition into the target. The trigger, conditions, and restrictions of such a transition are not used for the direct jump.

With direct state control, stuck processes are recoverable without deleting the instance or editing persistence directly. An operator repositions a failed invoice approval from an error activity back to "Pending Approval" and the process continues.

What it is

Think of direct state control as a manual override on a machine. Normal operation follows a configured route with its checks and steps. The override moves the machine to an approved position directly - useful when the normal controls cannot work because the machine is in an unexpected state.

SetStateAsync is the runtime API that performs the override. It takes a process instance identifier and a target state name. The runtime can move the process only to an activity whose State matches that name and whose IsForSetState option is enabled. If no such activity exists, the runtime throws an exception.

The method supports two modes controlled by the PreventExecution parameter:

  • With execution (default, PreventExecution = false) - the runtime runs the target activity's Implementation, including its configured actions, and then processes automatic transitions from that activity normally. Conditions on those automatic transitions are evaluated.
  • Without execution (PreventExecution = true) - the runtime persists the target activity without running its Implementation or processing automatic transitions. The process is set to Idled, or to Finalized when the target is final.

The direct jump does not execute the current activity's Implementation or a configured transition into the target. With execution, configured process logging can record the set-state execution and the resulting activity and state changes. The without-execution path updates persistence but does not produce the same execution log, so add application-level auditing if the operation must always be recorded.

For developers: call WorkflowRuntime.SetStateAsync(SetStateParams) with the process ID and target state name. In the scheme, give the target activity a State and set IsForSetState = true. Set PreventExecution = true to skip target activity execution. See Set State Directly reference for API details.

Why it matters

Direct state control delivers these outcomes:

  • Recover stuck processes without data loss - a process instance stuck in an error loop or an invalid state can be repositioned to a valid activity. All its parameters and history are preserved - no need to delete and restart.

  • Bypass an unavailable route - the direct jump does not use a command, actor rule, or configured transition into the target. The target still needs a matching State and IsForSetState = true. With execution enabled, conditions on automatic transitions from the target are processed normally.

  • Use the runtime instead of editing the database - modifying the current activity in the database directly bypasses runtime processing. SetStateAsync validates the target, updates persistence through the runtime, and leaves the process Idled or Finalized when execution finishes at that activity.

  • Two modes for different recovery scenarios - with execution lets the process auto-advance after the state change. Without execution lets the operator place the process precisely and decide the next step manually.

Who it is for

Evaluator (CEO, CTO, PM): direct state control reduces the operational impact of stuck processes. When exposed through controlled administrative tooling, a failed instance can be recovered without database access or losing the process data accumulated so far.

Developer: SetStateAsync is a single API call. The target activity must be marked with IsForSetState = true in the scheme - you decide which activities are safe to jump to. The method does not replace ExecuteCommandAsync for normal flow; it is an escape hatch for cases where normal execution cannot apply. See Set State Directly reference for the API reference.

Enterprise architect: the direct jump does not perform the actor authorization used for command execution. Your application must restrict access to this API at the integration layer. When execution is enabled, the target activity's actions run and conditions on its automatic transitions are evaluated normally.

When to use it

Use direct state control for interventions that cannot be accomplished through normal command execution. Typical examples:

  • Recovering stuck instances - a support ticket workflow encountered an error during a web service call and the error handling activity has no outgoing command. An operator uses SetStateAsync to move the instance back to an earlier activity and retry.

  • Applying state migrations after scheme changes - a scheme update removed a transition path that running instances depended on. Use SetStateAsync in a migration script to reposition affected instances to compatible activities.

  • Admin troubleshooting tools - build an admin panel that lets support staff move instances between states for testing or diagnosis. The IsForSetState flag on activities limits which states are reachable.

Do not use SetStateAsync as a substitute for ExecuteCommandAsync in normal process flow. Reserve it for cases where the normal command pipeline cannot apply.

How it compares

The alternatives to SetStateAsync for dealing with stuck processes are destructive or risky. The table below shows the tradeoffs.

Comparison of stuck process recovery approaches
ApproachRiskResult
Delete and restartLoses all process parameters, history, and context accumulated in the stuck instance.Data loss. User must re-enter information.
Direct database updateSkips all runtime validation - may leave the process in an inconsistent state with orphaned timers, wrong status, or broken parameter state.Runtime consistency can be lost.
Workflow Engine SetStateAsyncValidates the target activity and updates persistence through the runtime. Target actions may have side effects unless execution is prevented.The process keeps its parameters and existing history. Add application-level auditing if required.

Frequently asked questions

When should I use SetStateAsync instead of ExecuteCommandAsync?

Use ExecuteCommandAsync for normal process progression where conditions, permissions, and actions should be evaluated. Use SetStateAsync only for manual overrides - recovering stuck instances, migrating process state after a scheme change, or building tooling that needs to reposition instances outside the normal flow.

Do I need to set IsForSetState on every activity I want to jump to?

Yes. A target activity must have IsForSetState = true and a non-empty State matching the requested state name. Attempting to set an unavailable state causes the runtime to throw ActivityNotFoundException. The target is identified by its state name, not its activity name.

What is the difference between SetStateAsync with and without execution?

With execution (default), the runtime runs the target activity's Implementation and then processes automatic transitions from it. Without execution (PreventExecution = true), the runtime persists the target without running its Implementation or automatic transitions, then sets the process to Idled or Finalized.

Which activity actions does SetStateAsync execute?

It does not run the current activity's Implementation. With PreventExecution = false, it runs the target activity's Implementation and may continue through automatic transitions. With PreventExecution = true, it does not run the target activity or process its automatic transitions.

What are the security implications of SetStateAsync?

The direct jump does not perform the actor authorization used by ExecuteCommandAsync. Access to this method in your application should be controlled according to your security requirements - the runtime does not validate whether the supplied identity may perform this operation.

See also