temporalio/temporal · critical
Failed to get HSM operation log: %v
Error message
Failed to get HSM operation log: %v
What it means
When collecting tombstones for a workflow's HSM (hierarchical state machine) nodes, the code calls ms.stateMachineNode.OpLog() to read the pending operation log. If that returns an error — meaning the in-memory HSM tree node is corrupted or the operation log cannot be read — the code panics with "Failed to get HSM operation log: %v" instead of continuing, because proceeding without the op log would drop delete tombstones and silently corrupt replication.
Source
Thrown at service/history/workflow/mutable_state_impl.go:8207
// snapshot or mutation.
return
}
if !ms.transitionHistoryEnabled {
// transition history is not enabled
return
}
if len(ms.executionInfo.TransitionHistory) == 0 {
// in an unknown state
return
}
var tombstones []*persistencespb.StateMachineTombstone
if ms.stateMachineNode != nil {
opLog, err := ms.stateMachineNode.OpLog()
if err != nil {
panic(fmt.Sprintf("Failed to get HSM operation log: %v", err))
}
for _, op := range opLog {
if deleteOp, ok := op.(hsm.DeleteOperation); ok {
path := deleteOp.Path()
if len(path) == 0 {
continue // Skip root deletion
}
tombstone := &persistencespb.StateMachineTombstone{
StateMachineKey: &persistencespb.StateMachineTombstone_StateMachinePath{
StateMachinePath: &persistencespb.StateMachinePath{
Path: make([]*persistencespb.StateMachineKey, len(path)),
},
},
}
for i, key := range path {View on GitHub (pinned to bde624efd1)
Solutions
- Capture the underlying error from the panic message and the workflow execution identifiers, then report it — this indicates a CHASM internal bug, not user error.
- Retry the operation; if state is rebuilt from persistence the op log may load cleanly.
- Check whether the workflow history/mutable state was modified by an experimental or custom CHASM feature and disable it.
- Upgrade to a server version with the relevant CHASM fix if one exists.
Defensive patterns
Strategy: try-catch
Validate before calling
// Internal invariant — no user-side pre-check. Server operators can recover state by: // temporal --ns <ns> workflow reset --wid <wid> --reset-type LastContinuedAsNew temporal --ns my-ns workflow reset --wid <workflow-id> --reset-type LastContinuedAsNew
Try / catch
// Server-side pattern (not user-catchable): convert panic to error at the // transaction boundary via the existing panic-to-error recovery in // (n *historyEngineImpl).Execute, then surface a 500 INTERNAL to the caller.
Prevention
- Avoid experimental CHASM/HSM flags in production unless required.
- Upgrade promptly when CHASM fixes are released.
- Reset affected workflow executions to recover corrupted in-memory state.
- Preserve the panic error text and execution IDs for bug reports.
When it happens
Trigger: Calling the mutable-state method that gathers StateMachineTombstones (during closeTransaction / generating replication state) when the stateMachineNode's OpLog() errors, i.e. an inconsistent or corrupted CHASM state machine tree in memory.
Common situations: CHASM/HSM internal invariant violations, bugs in state machine tree manipulation, or state restored/reloaded inconsistently mid-transaction.
Related errors
- ErrStaleReference
- %w: %w
- ErrStaleState
- component is not registered to a library
- task is not registered to a library
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/2960ccd2a62f6689.
Report an issue: GitHub.