temporalio/temporal · error

failed to read version demotion signal configuration: %w

Error message

failed to read version demotion signal configuration: %w

What it means

shouldUseVersionDemotionSignal reads a MutableSideEffect (versionDemotionSignalMutableSideEffect) to decide whether version demotion must go through a signal. If reading the side-effect value fails, the error is wrapped and propagated to setRamp/handleSetCurrent, blocking the requested ramp or current-version change.

Source

Thrown at service/worker/workerdeployment/workflow.go:140

	if workflow.GetVersion(ctx, versionDemotionSignalChangeID, workflow.DefaultVersion, 0) == workflow.DefaultVersion {
		// Histories that have commit-routing-first (previous check), but predate this checkpoint are
		// workflows that already used signal-based demotion. They must continue
		// on the signal path to avoid a non-determinism error, regardless of the
		// current dynamic config value.
		// OSS 1.31 histories never reach here because they didn't have commit-routing-first.
		return true, nil
	}

	var enabled bool
	err := workflow.MutableSideEffect(
		ctx,
		versionDemotionSignalMutableSideEffect,
		func(workflow.Context) any { return versionDemotionSignalEnabledGetter() },
		func(a, b any) bool { return a == b },
	).Get(&enabled)
	if err != nil {
		return false, fmt.Errorf("failed to read version demotion signal configuration: %w", err)
	}
	return enabled, nil
}

func (d *WorkflowRunner) listenToSignals(ctx workflow.Context) {
	forceCANSignalChannel := workflow.GetSignalChannel(ctx, ForceCANSignalName)
	syncVersionSummaryChannel := workflow.GetSignalChannel(ctx, SyncVersionSummarySignal)
	propagationCompleteChannel := workflow.GetSignalChannel(ctx, PropagationCompleteSignal)

	d.signalHandler.signalSelector.AddReceive(forceCANSignalChannel, func(c workflow.ReceiveChannel, more bool) {
		d.signalHandler.processingSignals++
		defer func() { d.signalHandler.processingSignals-- }()

		var args *deploymentspb.ForceCANDeploymentSignalArgs
		c.Receive(ctx, &args)
		d.forceCAN = true

		// Apply override state if provided

View on GitHub (pinned to bde624efd1)

Solutions

  1. Check workflow history for the versionDemotionSignal MutableSideEffect record; a missing/corrupt record needs a history-level fix
  2. Retry the update (SetCurrentVersion/SetRampingVersion) — a fresh workflow execution may recover transient replay issues
  3. Report with workflow ID/run ID if persistent; mark the deployment series state manually via supported APIs if demotion is blocked
Defensive patterns

Strategy: retry

Try / catch

err := deploymentHandle.SetCurrentVersion(ctx, req)
if err != nil && strings.Contains(err.Error(), "failed to read version demotion signal configuration") {
    // transient replay issue — retry the update after backoff
}

Prevention

When it happens

Trigger: workflow.SideEffect/MutableSideEffect Get returning an error, typically deterministic-execution problems, side-effect history corruption, or workflow panic recovery during a SetRampingVersion/SetCurrentVersion update handling.

Common situations: Workflow history replay issues after a server/SDK upgrade; continued-as-new workflows with missing side-effect records; state store corruption.

Related errors


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