{"record":{"id":"c44db75ed28d3272","repo":"temporalio/temporal","slug":"w-zombie-workflow-cannot-be-updated","errorCode":null,"errorMessage":"%w: zombie workflow cannot be updated","messagePattern":"%w: zombie workflow cannot be updated","errorType":"error_code","errorClass":"NotFound (wrapped ErrStaleReference)","httpStatus":null,"severity":"error","filePath":"service/history/consts/const.go","lineNumber":53,"sourceCode":"\t// task is no longer needed.\n\t// It is also a NotFoundError to indicate to API callers that the object they're targeting is not found.\n\tErrStaleReference = serviceerror.NewNotFound(\"stale reference\")\n\t// ErrStaleState is the error returned during state update indicating that cached mutable state could be stale after\n\t// a reload attempt.\n\tErrStaleState = staleStateError{}\n\t// ErrTransitionHistoryDisabled is the error to indicate that transition history is disabled for the state machine,\n\t// and request cannot be processed before it's re-enabled.\n\tErrTransitionHistoryDisabled = serviceerror.NewFailedPrecondition(\"Transition history disabled\")\n\t// ErrActivityTaskNotFound is the error to indicate activity task could be duplicate and activity already completed\n\tErrActivityTaskNotFound = serviceerror.NewNotFound(\"invalid activityID or activity already timed out or invoking workflow is completed\")\n\t// ErrActivityNotFound is the error to indicate that there is no pending activity with this ID\n\tErrActivityNotFound = serviceerror.NewNotFound(\"Can't find pending activity with such ID. Invalid activityID or activity already completed\")\n\t// ErrActivityTaskNotCancelRequested is the error to indicate activity to be canceled is not cancel requested\n\tErrActivityTaskNotCancelRequested = serviceerror.NewInvalidArgument(\"unable to mark activity as canceled without activity being request canceled first\")\n\t// ErrWorkflowCompleted is the error to indicate workflow execution already completed\n\tErrWorkflowCompleted = serviceerror.NewNotFound(\"workflow execution already completed\")\n\t// ErrWorkflowZombie is the error to indicate workflow execution is in zombie state and cannot be updated\n\tErrWorkflowZombie = fmt.Errorf(\"%w: zombie workflow cannot be updated\", ErrStaleReference)\n\t// ErrWorkflowExecutionNotFound is the error to indicate workflow execution does not exist\n\tErrWorkflowExecutionNotFound = serviceerror.NewNotFound(\"workflow execution not found\")\n\t// ErrWorkflowParent is the error to parent execution is given and mismatch\n\tErrWorkflowParent = serviceerror.NewNotFound(\"workflow parent does not match\")\n\t// ErrDeserializingToken is the error to indicate task token is invalid\n\tErrDeserializingToken = serviceerror.NewInvalidArgument(\"error deserializing task token\")\n\t// ErrSignalsLimitExceeded is the error indicating limit reached for maximum number of signal events\n\tErrSignalsLimitExceeded = serviceerror.NewInvalidArgument(\"exceeded workflow execution limit for signal events\")\n\t// ErrWorkflowClosing is the error indicating requests to workflow can not be applied as workflow is closing\n\tErrWorkflowClosing = &serviceerror.ResourceExhausted{\n\t\tCause:   enumspb.RESOURCE_EXHAUSTED_CAUSE_BUSY_WORKFLOW,\n\t\tScope:   enumspb.RESOURCE_EXHAUSTED_SCOPE_NAMESPACE,\n\t\tMessage: \"workflow operation can not be applied because workflow is closing\",\n\t}\n\t// ErrEventsAterWorkflowFinish is the error indicating server error trying to write events after workflow finish event\n\tErrEventsAterWorkflowFinish = serviceerror.NewInternal(\"error validating last event being workflow finish event\")\n\t// ErrQueryEnteredInvalidState is error indicating query entered invalid state\n\tErrQueryEnteredInvalidState = serviceerror.NewInvalidArgument(\"query entered invalid state, this should be impossible\")","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/service/history/consts/const.go#L35-L71","documentation":"ErrWorkflowZombie wraps ErrStaleReference and indicates a workflow execution is in the zombie state — the workflow already completed but its mutable state still exists, so it can no longer accept updates. History service returns it from CHASM-related validation paths (validateNotZombieWorkflow, validateChasmSideEffectTask, executeChasmPureTimers).","triggerScenarios":"Any attempt to update a workflow whose mutable state shows zombie status: validating a CHASM side-effect task, executing CHASM pure timers or state-machine timers against a workflow that completed before the task ran.","commonSituations":"A workflow completed (timeout, cancellation, termination) while completion/replication tasks were still in flight; replication lag lets one cluster finish the workflow while another still processes tasks for it; retry of an already-applied task after workflow completion.","solutions":["Treat as stale reference: discard the task/update rather than retrying — the workflow is done","Check for replication lag or duplicate task delivery if this happens frequently for the same workflow","If the workflow should not be complete, investigate why it finished (timeout, termination) before resending updates"],"exampleFix":"// before\nerr := workflowContext.Update(...)\n// after\nerr := workflowContext.Update(...)\nif errors.Is(err, consts.ErrWorkflowZombie) {\n\t// workflow already completed; drop the update\n\treturn nil\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isZombieWorkflow(err error) bool { return errors.Is(err, consts.ErrWorkflowZombie) }","tryCatchPattern":"if err := updateWorkflow(ctx, wf); err != nil {\n\tif errors.Is(err, consts.ErrWorkflowZombie) {\n\t\t// workflow already completed; drop the update idempotently\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Check workflow completion status before issuing updates/tasks","Design task handlers to tolerate workflow-completed races idempotently","Monitor replication lag which widens the zombie window"],"tags":["go","history-service","chasm","stale-reference"],"backgroundTag":"zombie-workflow-update","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}