Skip to content

fix(db): don't hint missing ban indexes in PruneBans (#1578) - #1581

Open
rumblefrog wants to merge 2 commits into
mainfrom
fix/1578-prunebans-missing-indexes
Open

rumblefrog wants to merge 2 commits into
mainfrom
fix/1578-prunebans-missing-indexes

Conversation

@rumblefrog

Copy link
Copy Markdown
Member

Fixes #1578.

Problem

#1577 (2.2.1) added FORCE INDEX (type_authid) / FORCE INDEX (type_ip) to the submission lookup in PruneBans(). Some long-upgraded installs don't have those two indexes on :prefix_bans. 702.php creates them, but the updater only runs scripts above the stored config.version, so an install that moved past 702 without running it never got them. MariaDB treats a hint on a missing index as error 1176, not a no-op. As a result, the Ban List page and the add / edit ban flows (PruneBans() callers: page.banlist.php, admin.edit.ban.php, api_bans_add) fatal with:

SQLSTATE[42000]: 1176 Key 'type_authid' doesn't exist in table 'BSteam'

Fix

  • PruneBans(): drop the index hints. When the indexes exist, the optimizer picks them for each arm on its own. The reviewer checked this against a 200k-ban table after ANALYZE.
  • web/updater/data/811.php (registered in store.json): checks information_schema.STATISTICS and adds whichever of type_authid / type_ip is missing, in a single ALTER TABLE. This makes upgraded installs match struc.sql. It's idempotent and portable (no MariaDB-only ADD INDEX IF NOT EXISTS), and it's a no-op on fresh installs, which already have both indexes.
  • Docs: a new "Key doesn't exist" entry in troubleshooting/database-errors.md with the manual SQL workaround, plus an AGENTS.md Database-conventions rule against index hints on indexes that upgraded installs may lack.

Tests

web/tests/integration/BansCompositeIndexesTest.php:

  • PruneBans() archives matching Steam / IP submissions with both indexes dropped. On main this test fails with the exact 1176 error from the issue.
  • The migration recreates both indexes with the struc.sql column order.
  • If only one index is missing, the migration adds just that one.
  • Re-running the migration adds no duplicates.
  • tearDown restores the schema.

Local gates: PHPStan is clean. PHPUnit passes apart from the six PluginVersionResolveTest cases, which fail only because the dev container doesn't mount game/; they're unrelated and pass in CI. UpdaterMigrationPortableSqlTest passes.

An adversarial review pass found no blockers. Its findings are addressed in the second commit: the corrected list of affected surfaces, a single combined ALTER so old MyISAM tables are rebuilt once, the type_ip error variant in the docs, and a tighter rationale for the existing :prefix_comms FORCE INDEX (created) hints.

2.2.1's PruneBans() used FORCE INDEX (type_authid / type_ip) on
:prefix_bans. Long-upgraded installs can lack those indexes, and a hint
on a missing index is MariaDB error 1176, which fataled the banlist,
servers, and dashboard pages.

Drop the hints and add updater migration 811 that creates either index
when missing, so upgraded installs converge with struc.sql.
Combine missing-index ALTERs into one statement, correct the list of
affected surfaces (banlist + add/edit ban, not home/servers), add the
type_ip error variant to the troubleshooting entry, and tighten the
AGENTS.md rationale for the comms FORCE INDEX exception.
@rumblefrog
rumblefrog requested a review from a team September 28, 2026 21:03

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2.2.1: PruneBans() fails on upgraded installs missing type_authid/type_ip indexes on sb_bans

1 participant