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
- Re-run the bootstrap reconciliation once no concurrent bootstrap job is active
- Inspect tb_app rows for the tenant ID and restore app_id = reserved tenant ID if manually altered
- Serialize bootstrap runs (single reconciler / advisory lock) to prevent concurrent mutation
- 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
- Run only one bootstrap reconciler per tenant
- Never hand-edit app_id on tb_app rows
- Gate migrations touching tb_app against running bootstrap jobs
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
- reserved tenant bootstrap app is disabled or deleted
- tenant bootstrap API key is already assigned to another…
- tenant bootstrap API key conflicts with an unmanaged…
- ensure tenant bootstrap app failed
- check tenant bootstrap API key ownership failed
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_authView on GitHub (pinned to 5e758547a8)