bytebase/bytebase · error

failed to refresh active stale plan check run for approval i

Error message

failed to refresh active stale plan check run for approval input version

What it means

Error refreshing a plan check run whose status is still Available/Running but whose stored approval input version no longer matches the plan's current one (the plan changed mid-flight). The evaluator creates a fresh check run so the scheduler re-checks against the new inputs; failure is logged with structured fields and wrapped.

Source

Thrown at backend/component/review/evaluator.go:669

		if planCheckRun.Status == store.PlanCheckRunStatusAvailable || planCheckRun.Status == store.PlanCheckRunStatusRunning {
			if planCheckRun.Result.GetApprovalInputVersion() == approvalInputVersion {
				return nil, approvalInputVersion, false, nil
			}
			refreshed, err := stores.CreatePlanCheckRun(ctx, &store.PlanCheckRunMessage{
				ProjectID: issue.ProjectID,
				PlanUID:   plan.UID,
				Result: &storepb.PlanCheckRunResult{
					ApprovalInputVersion: approvalInputVersion,
				},
			})
			if err != nil {
				slog.Error("failed to refresh active stale plan check run for approval input version",
					slog.String("project", issue.ProjectID),
					slog.Int64("issue_uid", issue.UID),
					slog.Int64("plan_uid", plan.UID),
					slog.Int64("approval_input_version", approvalInputVersion),
					log.BBError(err))
				return nil, approvalInputVersion, false, errors.Wrap(err, "failed to refresh active stale plan check run for approval input version")
			}
			_ = refreshed
			return nil, approvalInputVersion, false, nil
		}
		current, pending := isPlanCheckRunCurrentForApprovalInputVersion(planCheckRun, approvalInputVersion)
		if pending {
			return nil, approvalInputVersion, false, nil
		}
		if !current {
			refreshed, err := stores.RefreshPlanCheckRunIfStaleApprovalInputVersion(ctx, issue.ProjectID, plan.UID, approvalInputVersion)
			if err != nil {
				slog.Error("failed to refresh stale plan check run for approval input version",
					slog.String("project", issue.ProjectID),
					slog.Int64("issue_uid", issue.UID),
					slog.Int64("plan_uid", plan.UID),
					slog.Int64("approval_input_version", approvalInputVersion),
					log.BBError(err))
				return nil, approvalInputVersion, false, errors.Wrap(err, "failed to refresh stale plan check run for approval input version")

View on GitHub (pinned to 1870550677)

Solutions

  1. If the wrapped cause is a duplicate-key error, re-read the plan check run — the concurrent refresher likely succeeded.
  2. Verify metadata Postgres accepts writes (read-only mode, disk space).
  3. Retry the evaluation after transient failures.
  4. Serialize refreshes per-plan (advisory lock or single-writer scheduler) to avoid races.

Example fix

// before
_, err := stores.CreatePlanCheckRun(ctx, msg)
if err != nil { return errors.Wrap(err, "failed to refresh active stale plan check run...") }
// after: upsert instead of insert
_, err := stores.UpsertPlanCheckRun(ctx, msg) // ON CONFLICT (project, plan_uid) DO UPDATE
if err != nil { return errors.Wrap(err, "...") }
Defensive patterns

Strategy: retry

Validate before calling

// detect stale version before refreshing
current, pending := isPlanCheckRunCurrentForApprovalInputVersion(planCheckRun, approvalInputVersion)
if pending || current { return nil } // no refresh needed

Try / catch

if _, err := stores.CreatePlanCheckRun(ctx, msg); err != nil {
    if isUniqueViolation(err) { return nil } // another refresher won
    slog.Error("failed to refresh active stale plan check run", log.BBError(err))
    return errors.Wrap(err, "failed to refresh active stale plan check run for approval input version")
}

Prevention

When it happens

Trigger: planCheckRun is Available/Running with a stale ApprovalInputVersion, and CreatePlanCheckRun fails while writing the replacement: unique-constraint race, metadata write failure, or connection loss.

Common situations: Plan edited while its check was running; two evaluators racing to refresh the same stale row; metadata DB read-only/full disk; deadlock with the check scheduler updating the same row.

Related errors


AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06). Data as JSON: /api/errors/dc47b42ef5ab45f4. Report an issue: GitHub.