iflytek/astron-agent · error

check tenant bootstrap managed credential failed

Error message

check tenant bootstrap managed credential failed: %w

What it means

findTenantBootstrapCredential wraps a database error that occurred while querying tb_auth for a managed (tenant-bootstrap-marked) credential row during tenant bootstrap reconciliation. The %w wrapper means an underlying MySQL/driver error was returned by QueryRowContext/Scan and it is not sql.ErrNoRows. It signals infrastructure failure of the credential-collision check, not a credential conflict.

Solutions

  1. Check tenant service logs for the wrapped underlying driver error (%v of the cause) to identify the exact MySQL failure.
  2. Verify MySQL connectivity, credentials, and that the tenant service can reach the DB host/port.
  3. Confirm schema migrations for tb_auth (including extend and is_delete columns) have been applied.
  4. If lock-wait timeouts appear, reduce concurrency of bootstrap reconciliation or raise innodb_lock_wait_timeout.
  5. Retry the reconciliation once connectivity is restored; the operation is transactional and safe to re-run.

Example fix

// before: no health check before reconcile
reconcileTenantBootstrapTransaction(ctx, db, cfg)

// after: verify DB reachable first
if err := db.PingContext(ctx); err != nil {
    return fmt.Errorf("database unavailable, skipping reconcile: %w", err)
}
return reconcileTenantBootstrapTransaction(ctx, db, cfg)
Defensive patterns

Strategy: retry

Validate before calling

if err := db.PingContext(ctx); err != nil { return fmt.Errorf("db not reachable before bootstrap reconcile: %w", err) }

Try / catch

err := reconcileTenantBootstrapTransaction(ctx, tx, cfg)
var retryable *mysql.MySQLError
if errors.As(err, &retryable) && isTransientCode(retryable.Number) {
    // retry with backoff
}

Prevention

When it happens

Trigger: The second QueryRowContext inside findTenantBootstrapCredential (SELECT api_secret, is_delete FROM tb_auth WHERE app_id=? AND api_key=? AND COALESCE(extend,'')<>? ... FOR UPDATE) fails with any error other than sql.ErrNoRows, e.g. connection drop, lock wait timeout, table missing, or permissions error, while reconcileTenantBootstrapTransaction runs inside its DB transaction.

Common situations: MySQL is restarting or unreachable mid-transaction; the FOR UPDATE row lock times out under contention from concurrent bootstrap reconcilers; migrations were not applied so tb_auth or the extend column does not exist; the DB user lacks SELECT privilege on tb_auth.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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

Appendix: source

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

	err = transaction.QueryRowContext(
		ctx,
		`SELECT api_secret, is_delete
	FROM tb_auth
	WHERE app_id = ? AND api_key = ? AND COALESCE(extend, '') <> ?
	LIMIT 1 FOR UPDATE`,
		credentials.TenantID,
		credentials.APIKey,
		tenantBootstrapManagedMarker,
	).Scan(&unmanagedSecret, &unmanagedIsDelete)
	if err == nil {
		if !unmanagedSecret.Valid || !unmanagedIsDelete.Valid || unmanagedIsDelete.Bool ||
			subtle.ConstantTimeCompare([]byte(unmanagedSecret.String), []byte(credentials.Secret)) != 1 {
			return false, errors.New("tenant bootstrap API key conflicts with an unmanaged credential")
		}
		return true, nil
	}
	if err != nil && !errors.Is(err, sql.ErrNoRows) {
		return false, fmt.Errorf("check tenant bootstrap managed credential failed: %w", err)
	}
	return false, nil
}

func adoptTenantBootstrapCredential(
	ctx context.Context,
	transaction bootstrapTransaction,
	credentials config.TenantBootstrapCredentials,
	now string,
) error {
	// A strong pair explicitly configured by the deployment may already have
	// been created through Tenant's public API on an older release. Because it
	// belongs to the reserved app and exactly matches the current deployment
	// Secret, adopt it into managed ownership so a later rotation can retire it.
	if _, err := transaction.ExecContext(
		ctx,
		`UPDATE tb_auth
SET extend = ?, update_time = ?

View on GitHub (pinned to 5e758547a8)