iflytek/astron-agent · error

locked tenant bootstrap app does not match the reserved…

Error message

locked tenant bootstrap app does not match the reserved tenant ID

What it means

During tenant bootstrap reconciliation, ensureAndLockTenantBootstrapApp takes a FOR UPDATE row lock on tb_app using the reserved tenant ID and asserts the locked row's app_id equals credentials.TenantID. A mismatch means the bootstrap transaction loaded a row whose app_id differs from the reserved tenant ID — an internal data inconsistency, since the query selects by app_id = tenant_id, indicating concurrent modification or schema/state corruption between lock and read.

Solutions

  1. Re-run the bootstrap reconciliation once no concurrent bootstrap job is active
  2. Inspect tb_app rows for the tenant ID and restore app_id = reserved tenant ID if manually altered
  3. Serialize bootstrap runs (single reconciler / advisory lock) to prevent concurrent mutation
  4. Check for scripts/migrations that rewrite app_id and gate them against bootstrap
Defensive patterns

Strategy: try-catch

Try / catch

if err := reconcileBootstrap(ctx, creds); err != nil && strings.Contains(err.Error(), "does not match the reserved tenant ID") { log.Error("bootstrap app row mutated concurrently; re-running after quiesce"); return retryAfterLockQuiesce(ctx, creds) }

Prevention

When it happens

Trigger: reconcileTenantBootstrapTransaction runs while another process deletes/recreates the app row, changing app_id between the write and the locked read, or manual DB edits moved/renamed app_id values.

Common situations: Concurrent bootstrap jobs on the same tenant, manual database surgery on tb_app, or a migration that rewrote app_id values while bootstrap runs.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/c69885958f3525db. Report an issue: GitHub.

Appendix: source

Thrown at core/tenant/tools/database/bootstrap_credentials.go:150

		"",
	); err != nil {
		return fmt.Errorf("ensure tenant bootstrap app failed: %w", err)
	}

	// Serialize reconciliation across replicas on the reserved app row before
	// taking any auth-index gap locks or rotating managed credentials.
	var lockedAppID string
	var lockedAppDisabled sql.NullBool
	var lockedAppDeleted sql.NullBool
	if err := transaction.QueryRowContext(
		ctx,
		`SELECT app_id, is_disable, is_delete FROM tb_app WHERE app_id = ? FOR UPDATE`,
		credentials.TenantID,
	).Scan(&lockedAppID, &lockedAppDisabled, &lockedAppDeleted); err != nil {
		return fmt.Errorf("lock tenant bootstrap app failed: %w", err)
	}
	if lockedAppID != credentials.TenantID {
		return errors.New("locked tenant bootstrap app does not match the reserved tenant ID")
	}
	if !lockedAppDisabled.Valid || lockedAppDisabled.Bool ||
		!lockedAppDeleted.Valid || lockedAppDeleted.Bool {
		return errors.New("reserved tenant bootstrap app is disabled or deleted")
	}
	return nil
}

func findTenantBootstrapCredential(
	ctx context.Context,
	transaction bootstrapTransaction,
	credentials config.TenantBootstrapCredentials,
) (bool, error) {
	var collisionOwner string
	err := transaction.QueryRowContext(
		ctx,
		`SELECT app_id
FROM tb_auth

View on GitHub (pinned to 5e758547a8)