{"record":{"id":"15b0e8e86bcd7bac","repo":"iflytek/astron-agent","slug":"tenant-bootstrap-api-key-is-already-assigned-to-another","errorCode":null,"errorMessage":"tenant bootstrap API key is already assigned to another active app","messagePattern":"tenant bootstrap API key is already assigned to another active app","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tenant/tools/database/bootstrap_credentials.go","lineNumber":175,"sourceCode":"}\n\nfunc findTenantBootstrapCredential(\n\tctx context.Context,\n\ttransaction bootstrapTransaction,\n\tcredentials config.TenantBootstrapCredentials,\n) (bool, error) {\n\tvar collisionOwner string\n\terr := transaction.QueryRowContext(\n\t\tctx,\n\t\t`SELECT app_id\nFROM tb_auth\nWHERE api_key = ? AND app_id <> ? AND is_delete = 0\nLIMIT 1 FOR UPDATE`,\n\t\tcredentials.APIKey,\n\t\tcredentials.TenantID,\n\t).Scan(&collisionOwner)\n\tif err == nil {\n\t\treturn false, errors.New(\"tenant bootstrap API key is already assigned to another active app\")\n\t}\n\tif !errors.Is(err, sql.ErrNoRows) {\n\t\treturn false, fmt.Errorf(\"check tenant bootstrap API key ownership failed: %w\", err)\n\t}\n\n\tvar unmanagedSecret sql.NullString\n\tvar unmanagedIsDelete sql.NullBool\n\terr = transaction.QueryRowContext(\n\t\tctx,\n\t\t`SELECT api_secret, is_delete\n\tFROM tb_auth\n\tWHERE app_id = ? AND api_key = ? AND COALESCE(extend, '') <> ?\n\tLIMIT 1 FOR UPDATE`,\n\t\tcredentials.TenantID,\n\t\tcredentials.APIKey,\n\t\ttenantBootstrapManagedMarker,\n\t).Scan(&unmanagedSecret, &unmanagedIsDelete)\n\tif err == nil {","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/tenant/tools/database/bootstrap_credentials.go#L157-L193","documentation":"findTenantBootstrapCredential checks whether the desired bootstrap API key is owned by a different, non-deleted app (SELECT ... WHERE api_key = ? AND app_id <> ? AND is_delete = 0 FOR UPDATE). If such a row exists, the key is already taken by another active app and assigning it to the bootstrap app would collide, so reconciliation aborts.","triggerScenarios":"reconcileTenantBootstrapTransaction runs while another app in tb_app holds the same api_key with is_delete=0; typically after the bootstrap api_key value was copied or reused for a different app.","commonSituations":"Manually duplicated API key across apps, another environment's seed data imported into this DB, or bootstrap credential config pointing at a key already issued to a regular app.","solutions":["Change the configured bootstrap API key to a unique value not present in tb_app","Soft-delete or re-key the app currently owning the conflicting api_key","Audit tb_app for duplicate api_key values and enforce uniqueness","Re-run bootstrap reconciliation after the collision is removed"],"exampleFix":"// before\nTenantBootstrap: {APIKey: \"ak-duplicate\"} // also owned by app X\n// after\nTenantBootstrap: {APIKey: \"ak-fresh-unique-value\"}","handlingStrategy":"validation","validationCode":"var n int\n_ = db.QueryRow(`SELECT COUNT(*) FROM tb_app WHERE api_key = ? AND app_id <> ? AND is_delete = 0`, apiKey, tenantID).Scan(&n)\nif n > 0 { return errors.New(\"bootstrap api_key already in use by another active app\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate bootstrap API keys from a dedicated reserved namespace","Add a unique index on api_key for active (is_delete=0) rows","Audit for duplicated keys after environment imports"],"tags":["go","mysql","bootstrap","unique-constraint"],"backgroundTag":"conflicting-config-options","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"}