temporalio/temporal · critical

unknown workflow state: %v

Error message

unknown workflow state: %v

What it means

MutableStateImpl panics with "unknown workflow state: %v" when a switch over the persisted WorkflowExecutionState (from executionState.State) hits a value that the code does not recognize. The switch maps each enumsspb.WORKFLOW_EXECUTION_STATE_* value (CREATED/RUNNING, COMPLETED, FAILED, CANCELED, CONTINUED_AS_NEW, ZOMBIE, CORRUPTED) to a boolean property; the default branch treats any other value as a data-integrity violation and crashes rather than returning a wrong answer. This is an internal invariant check, so it indicates the mutable state in memory carries a state enum that this Temporal build does not know about.

Source

Thrown at service/history/workflow/mutable_state_impl.go:1347

	// 2. stateInDB being completed does not guarantee this workflow being the current workflow
	// 3. stateInDB being zombie guarantees this workflow not being the current workflow
	// 4. stateInDB cannot be void, void is only possible when mutable state is just initialized

	switch ms.stateInDB {
	case enumsspb.WORKFLOW_EXECUTION_STATE_VOID:
		return false
	case enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:
		return true
	case enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:
		return true
	case enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED:
		return false
	case enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:
		return false
	case enumsspb.WORKFLOW_EXECUTION_STATE_CORRUPTED:
		return false
	default:
		panic(fmt.Sprintf("unknown workflow state: %v", ms.executionState.State))
	}
}

func (ms *MutableStateImpl) IsNonCurrentWorkflowGuaranteed() (bool, error) {
	switch ms.stateInDB {
	case enumsspb.WORKFLOW_EXECUTION_STATE_VOID:
		return true, nil
	case enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:
		return false, nil
	case enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:
		return false, nil
	case enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED:
		return false, nil
	case enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:
		return true, nil
	case enumsspb.WORKFLOW_EXECUTION_STATE_CORRUPTED:
		return false, nil
	default:

View on GitHub (pinned to bde624efd1)

Solutions

  1. Upgrade the Temporal server binary so all enumsspb.WORKFLOW_EXECUTION_STATE values in persistence are known to this build (eliminate version skew).
  2. Inspect the persisted WorkflowExecutionState for the failing execution (namespace/execution ID from the panic) and check for corrupted or out-of-range values.
  3. Check persistence migration/schema versions (schema tool) are up to date with the running server version.
  4. If reproducible on a current build, file a bug with the state value printed in the panic message.

Example fix

// before
default:
    panic(fmt.Sprintf("unknown workflow state: %v", ms.executionState.State))
// after: no user-side code fix; fix version skew / data. Server-side hardening could log and return false instead of panicking.
Defensive patterns

Strategy: validation

Validate before calling

// Operators: before restarting an old binary, confirm no persistence rows carry
// states unknown to it:
//   temporal --ns <ns> workflow show --wid <wid>  # inspect execution state
// In code, guard before interpreting:
if ms.ExecutionState.State == enumsspb.WORKFLOW_EXECUTION_STATE_UNSPECIFIED {
    // refuse to process rather than panicking downstream
}

Type guard

func isKnownWorkflowState(s enumsspb.WorkflowExecutionState) bool {
    switch s {
    case enumsspb.WORKFLOW_EXECUTION_STATE_CREATED,
        enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING,
        enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED,
        enumsspb.WORKFLOW_EXECUTION_STATE_FAILED,
        enumsspb.WORKFLOW_EXECUTION_STATE_CANCELED,
        enumsspb.WORKFLOW_EXECUTION_STATE_CONTINUED_AS_NEW,
        enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE,
        enumsspb.WORKFLOW_EXECUTION_STATE_CORRUPTED:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Calling ms.IsWorkflowExecutionRunning() (or the other Is* state predicates around line 1347) on a MutableStateImpl whose ms.executionState.State is not one of the enum values compiled into the binary — e.g. a persistence row written by a newer Temporal server that added a new WorkflowExecutionState enum value, or corrupted/deserialized state data.

Common situations: Rolling upgrade where a newer history service wrote a new enum value to the executions table and an older binary reloads it; version skew between server and persistence schema; hand-edited or migrated database rows; corrupted persistence payloads.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/eb7714ca15f1d6bb. Report an issue: GitHub.