iflytek/astron-agent · error

disable published legacy tenant credential failed

Error message

disable published legacy tenant credential failed: %w

What it means

rotateTenantBootstrapCredentials wraps a failure of the first UPDATE that soft-deletes the legacy published tenant credential (is_delete=1 WHERE api_key=legacyKey AND api_secret=legacySecret) in tb_auth. The %w wrap preserves the underlying MySQL/driver error. Rotation aborts so legacy and new credentials are never in an inconsistent half-rotated state.

Solutions

  1. Read the wrapped cause error from tenant logs to distinguish timeout, deadlock, or connectivity failure.
  2. Retry the rotation — it is transactional and idempotent (soft delete matches exact key/secret pair).
  3. Confirm the UPDATE runs on the primary DB, not a read-only replica or user lacking UPDATE privilege on tb_auth.
  4. Check index coverage on tb_auth.api_key/api_secret to avoid full-table-scan lock escalation.
  5. If deadlocks recur, schedule rotation outside peak traffic or serialize with an advisory lock.

Example fix

// before: rotation failure bubbles up unhandled
if err := reconcileTenantBootstrapTransaction(ctx, tx, cfg); err != nil {
    log.Fatalf("rotate failed: %v", err)
}

// after: retry with backoff before giving up
if err := retry.OnError(wait.Backoff{Steps: 3, Duration: time.Second}, isRetryableDBError, func() error {
    return reconcileTenantBootstrapTransaction(ctx, tx, cfg)
}); err != nil {
    log.Errorf("tenant credential rotation failed after retries: %v", err)
}
Defensive patterns

Strategy: retry

Validate before calling

var writable int
db.QueryRow("SELECT @@read_only = 0").Scan(&writable)
if writable != 1 { return errors.New("target DB is read-only; cannot rotate credentials") }

Try / catch

err := rotateTenantBootstrapCredentials(ctx, tx, cfg)
if err != nil {
    var myErr *mysql.MySQLError
    if errors.As(err, &myErr) && (myErr.Number == 1205 || myErr.Number == 1213) {
        // lock wait timeout / deadlock: retry
    }
}

Prevention

When it happens

Trigger: transaction.ExecContext("UPDATE tb_auth SET is_delete=1, update_time=? WHERE api_key=? AND api_secret=?") returns a non-nil error during credential rotation inside reconcileTenantBootstrapTransaction — deadlocks, lock wait timeout, lost connection, read-only target, or SQL syntax/schema mismatch.

Common situations: Legacy credential rows are numerous or heavily locked by other services during rotation; deployment points the service at a replica; connection drops mid-transaction; a botched migration removed api_key/api_secret indexes causing long scans and timeouts.

Related errors


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

Appendix: source

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

	return nil
}

func rotateTenantBootstrapCredentials(
	ctx context.Context,
	transaction bootstrapTransaction,
	credentials config.TenantBootstrapCredentials,
	now string,
) error {
	if _, err := transaction.ExecContext(
		ctx,
		`UPDATE tb_auth
SET is_delete = 1, update_time = ?
WHERE api_key = ? AND api_secret = ?`,
		now,
		config.LegacyTenantKey,
		config.LegacyTenantSecret,
	); err != nil {
		return fmt.Errorf("disable published legacy tenant credential failed: %w", err)
	}

	if _, err := transaction.ExecContext(
		ctx,
		`UPDATE tb_auth
SET is_delete = 1, update_time = ?
WHERE app_id = ? AND extend = ? AND api_key <> ?`,
		now,
		credentials.TenantID,
		tenantBootstrapManagedMarker,
		credentials.APIKey,
	); err != nil {
		return fmt.Errorf("retire previous managed tenant credential failed: %w", err)
	}
	if _, err := transaction.ExecContext(
		ctx,
		`INSERT INTO tb_auth
  (update_time, registration_time, app_id, api_key, api_secret, source, is_delete, extend)

View on GitHub (pinned to 5e758547a8)