bytebase/bytebase · error

failed to update active VCS provider user

Error message

failed to update active VCS provider user

What it means

TouchVCSProviderUser first attempts a fast-path UPDATE ... RETURNING true to refresh an already-active VCS provider user. If Scan returns an error other than sql.ErrNoRows — the statement itself failed rather than simply matching no row — the store wraps it as "failed to update active VCS provider user". sql.ErrNoRows is deliberately treated as "user not currently active" and falls through to the transactional insert/reactivate path.

Source

Thrown at backend/store/vcs_provider_user.go:69

	if payload == nil {
		payload = &storepb.VCSProviderUserPayload{}
	}
	payloadBytes, err := protojson.Marshal(payload)
	if err != nil {
		return false, errors.Wrapf(err, "failed to marshal VCS provider user payload")
	}

	vcsType := user.VCSType.String()
	var refreshed bool
	if err := s.GetDB().QueryRowContext(ctx, `
		UPDATE vcs_provider_user
		SET last_seen_at = now(), payload = $4
		WHERE workspace = $1 AND vcs_type = $2 AND user_id = $3
			AND last_seen_at >= now() - make_interval(secs => $5)
		RETURNING true
	`, workspace, vcsType, user.UserID, payloadBytes, activeWindow.Seconds()).Scan(&refreshed); err != nil {
		if err != sql.ErrNoRows {
			return false, errors.Wrapf(err, "failed to update active VCS provider user")
		}
	} else {
		return true, nil
	}

	tx, err := s.GetDB().BeginTx(ctx, nil)
	if err != nil {
		return false, errors.Wrapf(err, "failed to begin transaction")
	}
	defer tx.Rollback()

	if err := AcquireAdvisoryXactLockWithStringKey(ctx, tx, AdvisoryLockKeyVCSProviderUser, workspace); err != nil {
		return false, errors.Wrapf(err, "failed to acquire VCS provider user lock")
	}

	var active bool
	if err := tx.QueryRowContext(ctx, `
		SELECT last_seen_at >= now() - make_interval(secs => $4)

View on GitHub (pinned to 1870550677)

Solutions

  1. Check metadata DB health and retry; transient connection/context errors usually resolve on retry.
  2. Verify vcs_provider_user exists and matches LATEST.sql; run migrations if the table is missing.
  3. Increase context timeouts for the VCS touch path if deadline cancellations occur under load.
  4. Inspect the wrapped driver error (pg error code) to pinpoint server-side causes like lock contention or statement timeouts.

Example fix

// before
refreshed, err := store.TouchVCSProviderUser(ctx, ws, user, window, limit)
if err != nil {
	return fmt.Errorf("touch failed: %w", err)
}
// after (retry transient failures before giving up)
var refreshed bool
backoff := 100 * time.Millisecond
for i := 0; i < 3; i++ {
	r, err := store.TouchVCSProviderUser(ctx, ws, user, window, limit)
	if err == nil {
		refreshed = r
		break
	}
	if !isTransientNetErr(err) || i == 2 {
		return fmt.Errorf("touch failed: %w", err)
	}
	time.Sleep(backoff)
	backoff *= 2
}
Defensive patterns

Strategy: retry

Validate before calling

// preflight: ensure the table exists and inputs are non-empty before touching
var exists bool
_ = db.QueryRowContext(ctx, "SELECT to_regclass('vcs_provider_user') IS NOT NULL").Scan(&exists)
if !exists || workspace == "" || user.UserID == "" || user.VCSType == v1pb.VCSType_VCS_TYPE_UNSPECIFIED {
	return errors.New("invalid touch inputs or missing table")
}

Try / catch

refreshed, err := store.TouchVCSProviderUser(ctx, ws, user, window, limit)
if err != nil {
	if isTransientNetErr(err) {
		refreshed, err = store.TouchVCSProviderUser(retryCtx, ws, user, window, limit)
	}
	if err != nil {
		return fmt.Errorf("touch vcs provider user: %w", err)
	}
}

Prevention

When it happens

Trigger: Calling TouchVCSProviderUser during a metadata DB outage or connection-pool exhaustion; the request context is cancelled while the UPDATE executes; the vcs_provider_user table is missing (unmigrated schema); parameter type/constraint errors.

Common situations: License-limit check during a Postgres failover; timeouts under load when many VCS users hit the GitOps endpoint concurrently; app running against a schema missing vcs_provider_user; transient context deadline cancellation.

Related errors


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