iflytek/astron-agent · critical
ensure tenant bootstrap app failed
Error message
ensure tenant bootstrap app failed: %w
What it means
ensureAndLockTenantBootstrapApp inserts (or confirms) the reserved 'admin' bootstrap app row in tb_app; any SQL failure during that insert is wrapped as 'ensure tenant bootstrap app failed'. This runs inside the bootstrap transaction before credentials are rotated.
Solutions
- Read the wrapped cause: if duplicate-key, inspect the existing tb_app row for the reserved app_id and reconcile it manually or adopt it.
- Run database migrations/tools to ensure the schema matches what the bootstrap code expects.
- Grant the bootstrap MySQL user INSERT/SELECT/UPDATE/LOCK TABLES privileges on tb_app and tb_auth.
- Check MySQL connectivity and error log for transient failures, then re-run bootstrap (it is idempotent within its transaction).
Example fix
// before: failing due to unexpected pre-existing row
INSERT INTO tb_app (app_id, ...) VALUES ('reserved-tenant', ...)
-- after: pre-reconcile conflicting legacy row first
-- DELETE or UPDATE the legacy row for the reserved app_id, then re-run bootstrap
UPDATE tb_app SET is_delete = 1 WHERE app_id = 'reserved-tenant' AND source <> 'bootstrap'; Defensive patterns
Strategy: retry
Validate before calling
var n int
if err := db.QueryRow(`SELECT COUNT(*) FROM tb_app WHERE app_id = ?`, reservedID).Scan(&n); err != nil || n > 1 {
return fmt.Errorf("conflicting rows for reserved app %s", reservedID)
} Try / catch
if err := ensureAndLockTenantBootstrapApp(ctx, tx, creds, now); err != nil {
if isDuplicateKey(err) {
return adoptExistingBootstrapApp(ctx, tx, creds) // reconcile legacy row
}
return fmt.Errorf("ensure tenant bootstrap app failed: %w", err)
} Prevention
- Keep schema migrations in lockstep with bootstrap code expectations.
- Reserve the tenant app_id and exclude it from cleanup/deletion jobs.
- Grant the bootstrap DB user full DML privileges on tb_app.
When it happens
Trigger: The INSERT of the reserved tenant app fails — duplicate app_id from a conflicting row, schema mismatch, permission denied for the MySQL user, or connection loss.
Common situations: Manual/legacy data in tb_app already uses the reserved tenant ID with different columns; migration out of sync so tb_app lacks expected columns; bootstrap DB user lacks INSERT privilege; MySQL connection dropped mid-transaction.
Related errors
- locked tenant bootstrap app does not match the reserved…
- 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…
- check tenant bootstrap API key ownership failed
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/66e748cc6647c8b0.
Report an issue: GitHub.
Appendix: source
Thrown at core/tenant/tools/database/bootstrap_credentials.go:134
) error {
if _, err := transaction.ExecContext(
ctx,
`INSERT IGNORE INTO tb_app
(update_time, registration_time, app_id, app_name, dev_id, channel_id, source, is_disable, app_desc, is_delete, extend)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
now,
now,
credentials.TenantID,
"星辰租户",
1,
"0",
"admin",
false,
"星辰租户",
false,
"",
); 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 ||View on GitHub (pinned to 5e758547a8)