{"record":{"id":"66e748cc6647c8b0","repo":"iflytek/astron-agent","slug":"ensure-tenant-bootstrap-app-failed-w","errorCode":null,"errorMessage":"ensure tenant bootstrap app failed: %w","messagePattern":"ensure tenant bootstrap app failed: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"core/tenant/tools/database/bootstrap_credentials.go","lineNumber":134,"sourceCode":") error {\n\tif _, err := transaction.ExecContext(\n\t\tctx,\n\t\t`INSERT IGNORE INTO tb_app\n  (update_time, registration_time, app_id, app_name, dev_id, channel_id, source, is_disable, app_desc, is_delete, extend)\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\tnow,\n\t\tnow,\n\t\tcredentials.TenantID,\n\t\t\"星辰租户\",\n\t\t1,\n\t\t\"0\",\n\t\t\"admin\",\n\t\tfalse,\n\t\t\"星辰租户\",\n\t\tfalse,\n\t\t\"\",\n\t); err != nil {\n\t\treturn fmt.Errorf(\"ensure tenant bootstrap app failed: %w\", err)\n\t}\n\n\t// Serialize reconciliation across replicas on the reserved app row before\n\t// taking any auth-index gap locks or rotating managed credentials.\n\tvar lockedAppID string\n\tvar lockedAppDisabled sql.NullBool\n\tvar lockedAppDeleted sql.NullBool\n\tif err := transaction.QueryRowContext(\n\t\tctx,\n\t\t`SELECT app_id, is_disable, is_delete FROM tb_app WHERE app_id = ? FOR UPDATE`,\n\t\tcredentials.TenantID,\n\t).Scan(&lockedAppID, &lockedAppDisabled, &lockedAppDeleted); err != nil {\n\t\treturn fmt.Errorf(\"lock tenant bootstrap app failed: %w\", err)\n\t}\n\tif lockedAppID != credentials.TenantID {\n\t\treturn errors.New(\"locked tenant bootstrap app does not match the reserved tenant ID\")\n\t}\n\tif !lockedAppDisabled.Valid || lockedAppDisabled.Bool ||","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/tenant/tools/database/bootstrap_credentials.go#L116-L152","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before: failing due to unexpected pre-existing row\nINSERT INTO tb_app (app_id, ...) VALUES ('reserved-tenant', ...)\n-- after: pre-reconcile conflicting legacy row first\n-- DELETE or UPDATE the legacy row for the reserved app_id, then re-run bootstrap\nUPDATE tb_app SET is_delete = 1 WHERE app_id = 'reserved-tenant' AND source <> 'bootstrap';","handlingStrategy":"retry","validationCode":"var n int\nif err := db.QueryRow(`SELECT COUNT(*) FROM tb_app WHERE app_id = ?`, reservedID).Scan(&n); err != nil || n > 1 {\n    return fmt.Errorf(\"conflicting rows for reserved app %s\", reservedID)\n}","typeGuard":null,"tryCatchPattern":"if err := ensureAndLockTenantBootstrapApp(ctx, tx, creds, now); err != nil {\n    if isDuplicateKey(err) {\n        return adoptExistingBootstrapApp(ctx, tx, creds) // reconcile legacy row\n    }\n    return fmt.Errorf(\"ensure tenant bootstrap app failed: %w\", err)\n}","preventionTips":["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."],"tags":["go","mysql","insert","bootstrap"],"backgroundTag":"database-write-failed","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}