temporalio/temporal · critical

can't decode TweakablePolicies:

Error message

can't decode TweakablePolicies:

What it means

TweakablePolicies are captured via workflow.MutableSideEffect so all replayed executions see identical values. If the stored side-effect blob cannot be decoded into TweakablePolicies on replay, the workflow cannot proceed deterministically and panics. This indicates persisted data incompatible with the current struct definition.

Source

Thrown at service/worker/scheduler/workflow.go:1329

func (s *scheduler) checkConflict(token int64) error {
	if token == 0 || token == s.State.ConflictToken {
		return nil
	}
	return errUpdateConflict
}

func (s *scheduler) updateTweakables() {
	// Use MutableSideEffect so that we can change the defaults without breaking determinism.
	get := func(ctx workflow.Context) any {
		p := CurrentTweakablePolicies
		// Re-evaluates migration dynamic config each iteration.
		p.EnableCHASMMigration = s.enableCHASMMigration()
		p.MigrateWithRunningWorkflows = s.migrateWithRunningWorkflows()
		return p
	}
	eq := func(a, b any) bool { return a.(TweakablePolicies) == b.(TweakablePolicies) }
	if err := workflow.MutableSideEffect(s.ctx, "tweakables", get, eq).Get(&s.tweakables); err != nil {
		panic("can't decode TweakablePolicies:" + err.Error())
	}
}

func (s *scheduler) getCatchupWindow() time.Duration {
	cw := s.Schedule.Policies.CatchupWindow
	if cw == nil {
		return s.tweakables.DefaultCatchupWindow
	} else if cw.AsDuration() < s.tweakables.MinCatchupWindow {
		return s.tweakables.MinCatchupWindow
	} else {
		return cw.AsDuration()
	}
}

func (s *scheduler) resolveOverlapPolicy(overlapPolicy enumspb.ScheduleOverlapPolicy) enumspb.ScheduleOverlapPolicy {
	if overlapPolicy == enumspb.SCHEDULE_OVERLAP_POLICY_UNSPECIFIED {
		overlapPolicy = s.Schedule.Policies.OverlapPolicy
	}

View on GitHub (pinned to bde624efd1)

Solutions

  1. Run a worker version that matches the one that wrote the side-effect (version pinning / patching)
  2. Terminate and restart the schedule workflow so tweakables are re-captured from current schedule config
  3. Restore the workflow from a history point before the incompatible side-effect write
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: Raised in the scheduler workflow's tweakables loading path (service/worker/scheduler/workflow.go:1329) when workflow.MutableSideEffect(...).Get(&s.tweakables) returns a decode error — the stored blob was written by a different schema/version, or the value is corrupted/truncated.

Common situations: Upgrading Temporal across a TweakablePolicies struct change with an in-flight schedule; importing/replaying a workflow history produced by a mismatched version; corrupted persistence payload.

Related errors


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