temporalio/temporal · error

Reset point for %v points to previous run and CurrentRunOnly

Error message

Reset point for %v points to previous run and CurrentRunOnly is set

What it means

getResetPoint found the reset point for the given BuildId, but the point's RunId differs from the target execution's RunId while the currentRunOnly option is set. The library refuses to reset across runs when the caller restricted the operation to the current run.

Source

Thrown at service/worker/batcher/activities.go:1177

	buildId string,
	currentRunOnly bool,
) (workflowTaskEventID int64, err error) {
	res, err := frontendClient.DescribeWorkflowExecution(ctx, &workflowservice.DescribeWorkflowExecutionRequest{
		Namespace: namespaceStr,
		Execution: execution,
	})
	if err != nil {
		return 0, err
	}
	resetPoints := res.GetWorkflowExecutionInfo().GetAutoResetPoints().GetPoints()
	for _, point := range resetPoints {
		if point.BuildId == buildId {
			if !point.Resettable {
				return 0, fmt.Errorf("Reset point for %v is not resettable", buildId)
			} else if point.ExpireTime != nil && point.ExpireTime.AsTime().Before(time.Now()) {
				return 0, fmt.Errorf("Reset point for %v is expired", buildId)
			} else if execution.RunId != point.RunId && currentRunOnly {
				return 0, fmt.Errorf("Reset point for %v points to previous run and CurrentRunOnly is set", buildId)
			}
			execution.RunId = point.RunId
			return point.FirstWorkflowTaskCompletedId, nil
		}
	}
	return 0, fmt.Errorf("Can't find reset point for %v", buildId)
}

View on GitHub (pinned to bde624efd1)

Solutions

  1. Set CurrentRunOnly=false in the reset options to allow resetting to a point in a previous run.
  2. Pass the RunId of the run that actually recorded the reset point (the point's RunId) as the target execution.
  3. Use the ResetWorkflow API's ability to reset across runs (it creates a new run continuing from the old point) instead of run-restricted batch reset.
  4. If run restriction is required, first find a reset point recorded within the current run.

Example fix

// before
id, err := getResetEventIDByOptions(ctx, exec, &ResetOptions{BuildId: buildId, CurrentRunOnly: true})
// after
id, err := getResetEventIDByOptions(ctx, exec, &ResetOptions{BuildId: buildId, CurrentRunOnly: false})
Defensive patterns

Strategy: validation

Validate before calling

// ensure the point belongs to the current run when CurrentRunOnly is set
if opts.CurrentRunOnly {
  for _, p := range info.GetAutoResetPoints().GetPoints() {
    if p.GetBuildId() == buildId && p.GetRunId() != currentRunID {
      return fmt.Errorf("point for %s is on run %s; unset CurrentRunOnly", buildId, p.GetRunId())
    }
  }
}

Type guard

func pointInCurrentRun(p *deploymentpb.ResetPoint, runID string) bool {
  return p.GetRunId() == runID
}

Try / catch

if err := doReset(ctx, exec, buildId); err != nil {
  if strings.Contains(err.Error(), "points to previous run") {
    return doReset(ctx, exec, buildId) // retry without CurrentRunOnly
  }
  return err
}

Prevention

When it happens

Trigger: Invoking getResetEventIDByOptions/getResetPoint with CurrentRunOnly=true for a buildId whose auto-reset point was recorded on a previous run of the same workflow (execution.RunId != point.RunId).

Common situations: Workflows that continued-as-new after the bad deployment: the reset point belongs to an older run, and tooling that passes CurrentRunOnly fails; mismatched RunId because callers cache the original execution's RunId after the workflow has continued on a new run.

Related errors


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