Fix Backup Inventory 503 from unsupported Cosmos GROUP BY aggregate - #1295
Merged
Paul Lizer (paullizer) merged 1 commit intoAug 19, 2026
Conversation
Backup Inventory always failed to load, returning 503 and rendering 0 for available, full, and partial backups even when backups had completed. _get_data_management_backup_global_summary() computed its counts with "GROUP BY c.backup_type, c.status" combined with a non-VALUE aggregate (COUNT(1) AS count). The azure-cosmos Python client does not advertise support for that combination, so Cosmos rejects it during query plan negotiation with BadRequest "GroupBy NonValueAggregate", which surfaced to admins as a generic 503. This was not throttling or a missing index; the composite index was already aligned. The aggregate shipped with the summary feature, so Backup Inventory had never worked in any deployment. Replace the grouped aggregate with six bounded SELECT VALUE COUNT(1) queries via a new _count_data_management_backups() helper. VALUE aggregates are supported by the client and already used elsewhere in this module. This avoids projecting every backup row and aggregating client-side, which would grow unbounded as history accumulates. The SELECT TOP 1 latest-backup queries were already valid and are unchanged. FakeHistoryContainer previously implemented GROUP BY in Python, so the suite passed against a query that always failed in production. It now raises the real BadRequest error instead, and a new test asserts no emitted history query uses GROUP BY or a non-VALUE aggregate. Also add a hover tooltip and an (i) toggle explaining what Run Retention Cleanup does, including that "found no expired backups to delete" means every backup is still inside the retention window rather than an error. Validation: 14 passed in the history pagination suite; 159 passed across Data Management with only the known pre-existing durability failure. Regression probe restoring a grouped aggregate fails two tests with the exact production error. Fixes microsoft#1294
Paul Lizer (paullizer)
merged commit Aug 19, 2026
4850877
into
microsoft:Development
11 of 12 checks passed
Paul Lizer (paullizer)
added a commit
to paullizer/simplechat
that referenced
this pull request
Aug 19, 2026
Resolves conflicts introduced by PR microsoft#1295 (Backup Inventory GROUP BY fix) landing on Development first. - config.py: keep 0.260.003, which supersedes the 0.260.002 from microsoft#1295. - release_notes.md: keep both sections, newest first (0.260.003 above 0.260.002). Neither entry replaces the other. functions_data_management.py auto-merged cleanly; the two changes touch different regions (_count_data_management_backups vs _set_job_progress / _complete_job_step) and both are present after the merge. Validation: 177 passed across the Data Management suite, with only the two known pre-existing issues (swagger_wrapper collection error in test_admin_endpoint.py, and test_backup_recovery_and_admin_progress_are_bounded_and_sanitized).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1294
Problem
Backup Inventory in Admin Settings → Data Management always failed to load.
GET /api/admin/data-management/backupsreturned503, the panel showedBackup history is temporarily unavailable. Please try again., and every tile rendered0— even with successfully completed backups.Root Cause
_get_data_management_backup_global_summary()computed its counts with:The
azure-cosmosPython client does not advertise support forGroupBycombined with a non-VALUE aggregate (COUNT(1) AS count). Cosmos rejects the request during query plan negotiation:That
BadRequestpropagated out of_query_data_management_history_itemsand surfaced as a generic503.This was not throttling, indexing, or capacity — Cosmos Maintenance consistently reported the composite index as Aligned / 0 missing / 7 containers checked, and the
400entries withrequestCharge = 0inAzureDiagnosticsare the benign cross-partition query-plan negotiation. Because the aggregate shipped with the summary feature, Backup Inventory had never worked in any deployment.Why tests did not catch it
FakeHistoryContainerimplementedGROUP BY c.backup_type, c.statusin Python and returned grouped rows. The test double supported a query shape the real client cannot serve, so the suite passed against a query that always failed in production.Changes
functions_data_management.py— added_count_data_management_backups()and rewrote the summary to issue six boundedSELECT VALUE COUNT(1)queries (total,available,running,failed,full,partial). VALUE aggregates are supported by the client and already used elsewhere in this module.SELECT TOP 1 *latest-backup queries were already valid and are unchanged.admin_settings.html— added a hover tooltip and an(i)toggle that expands inline guidance next to Run Retention Cleanup, covering what gets deleted, what is protected, the 25-per-run cap, and thatfound no expired backups to deleteis expected rather than an error.test_data_management_history_pagination.py—FakeHistoryContainernow raises the realBadRequest ... GroupBy NonValueAggregateerror instead of emulatingGROUP BY, plus two new tests.Validation
functional_tests/test_data_management_history_pagination.py— 14 passed-k data_management) — 159 passed, only the known pre-existingtest_backup_recovery_and_admin_progress_are_bounded_and_sanitizedfailureRegression probe: restoring a grouped aggregate fails two tests with the exact production error, confirming they fail for the right reason:
Impact
GET /api/admin/data-management/backups5032000