Normal path
queued → planning → policy_evaluating → awaiting_approval → applying → succeeded- Plan only, speculative, and drift check runs finish after policy passes. The dashboard labels them Plan completed. A drift check reads Plan completed whether or not it found drift; the workspace’s drift status says which.
- A plan and apply run whose plan has no changes also finishes after policy. Approval and apply are skipped.
- A plan and apply run with changes waits for approval, then applies. The dashboard labels it Applied when it finishes.
In-progress statuses
| Status | Dashboard label | Meaning |
|---|---|---|
dispatch_pending |
Dispatch pending | The run was created and is about to be queued |
queued |
Queued | Waiting for a run environment |
planning |
Planning | OpenTofu is running plan |
plan_complete |
Plan complete | The plan finished; policy checks are next |
policy_evaluating |
Evaluating policy | Policy sets are checking the plan |
policy_passed |
Policy passed | Policy allows the run to continue |
awaiting_approval |
Awaiting approval | Waiting for someone to approve or discard the plan, for up to seven days. A failed soft-mandatory policy must be overridden first |
applying |
Applying | OpenTofu is running apply |
Final statuses
| Status | Dashboard label | Meaning | What to do |
|---|---|---|---|
succeeded |
Applied / Plan completed | The run finished | Nothing |
plan_failed |
Plan failed | OpenTofu returned an error during plan | Read the error in the run header, fix the configuration, and start a new run |
plan_credentials_required |
Plan credentials required | The workspace has no cloud credentials for this run | Set up cloud access for the workspace |
policy_failed |
Policy failed | A hard-mandatory policy found a problem, a policy errored, or a soft-mandatory policy failed on a plan that can’t be applied | Fix the finding and start a new run |
rejected |
Discarded | Someone discarded the plan | Start a new run if needed |
expired |
Expired | Nobody approved or discarded the plan within seven days | Push to the tracked branch or run tofu apply again |
canceled |
Canceled | Someone canceled the run before its apply started | Start a new run if needed |
apply_failed |
Apply failed | OpenTofu returned an error during apply | Read the error, fix it, and start a new run. Some resources may have changed |
apply_start_uncertain |
Apply start uncertain | StackShip can’t confirm whether apply started | Recover the run |
apply_interrupted |
Apply interrupted | The apply was canceled, force canceled, or stopped part-way | Recover the run |
needs_recovery |
Needs recovery | StackShip can’t confirm the result of the apply | Recover the run |
StackShip never reports an apply as successful unless it can confirm the new state was saved.
When a run ends before its apply starts, the run review
(GET /v1/runs/{run_id}/review) reports apply.status as skipped, like
the apply stage. When it ends before its policy evaluation finishes,
policy.status is failed or skipped, matching the policy stage.
Canceled runs
See Cancel a run for how to cancel.
- Before the apply starts, the run ends as Canceled. If the cancel arrived just as the apply was about to begin, the run page shows Canceled before the apply started.
- During an apply, OpenTofu is asked to stop at a safe point, which can take up to 15 minutes. The run ends as Applied if the apply finishes first, or Apply interrupted otherwise.
- Force canceling stops the apply immediately. The run ends as Apply interrupted, and the run page shows Force canceled during apply.
An interrupted apply keeps the workspace locked until you recover it.
Interrupted runs
The environment running a phase can occasionally be restarted for maintenance.
- An interrupted plan or policy check is retried once automatically. If the retry is also interrupted, the run fails and you can start a new one.
- An interrupted apply is never retried. OpenTofu is asked to stop at a safe point and save state. If the apply finishes anyway, the run succeeds. If OpenTofu stops part-way, the run ends as Apply interrupted; if the result can’t be confirmed, Needs recovery. In both cases, recover the run before starting a new one.
- If StackShip can prove an apply never started, for example because its environment failed to launch, the run ends as Apply failed, nothing changed, and the workspace is unlocked. Start a new run.
- If the workspace state changed after the plan was made, for example through
a local
tofu apply, the apply doesn’t start and the run ends as Apply failed. Start a new run to plan against the current state.
Long applies are the most exposed. If an apply regularly takes hours, consider splitting the workspace.
Recover an interrupted apply
If an apply is interrupted or its result is unclear, your infrastructure and the workspace state may no longer match. The workspace is locked and the run page shows an Operator recovery required panel.
Recovery requires the owner or admin role.
- Check the affected resources in your cloud provider.
- Read the recovery panel. It shows the workspace’s current state version and, if OpenTofu saved one, an emergency state snapshot.
- Enter a reason and confirm that you understand the workspace lock will be released.
- Choose one:
- Keep verified current state — keep the workspace’s current state.
- Import untrusted emergency state — replace the current state with the emergency snapshot captured during the interrupted apply. Offered only when the workspace state hasn’t changed since the run started.
- Start a new plan to reconcile any remaining differences.
After recovery, the run’s status stays Needs recovery (including runs
that were Apply interrupted or Apply start uncertain) as a historical
record, and the run page shows which option was chosen. Recovery is recorded
in the audit log. The API equivalent is
POST /v1/runs/{run_id}/actions/recover.
While recovery is pending, new runs on that workspace fail with a workspace-lock error that points you to the run to recover.