Repository navigation
fix(admin): purge the open entry from the edit view, and let the purge button be used twice - #253
Merged
Merged
Conversation
PurgeCacheButton set its loading state when a purge started and never cleared it. The button stays mounted after the dialog closes, so the next time the dialog opened its confirm button was a disabled spinner and the only way out was Cancel - until a reload remounted the component. Reset it in the same `finally` that closes the dialog, so success and failure both leave the control usable. Covered by e2e/tests/purge-controls.spec.ts, which lands with the edit-view purge fix on this branch.
The edit-view "Purge REST Cache" action sent the document's scalar fields as the route params. A Strapi 5 document's `id` field is the numeric row id, but a REST route's `:id` is the documentId, so the purge built a pattern like `^/api/articles/1\?` that no cache key can match. With clearRelatedCache on - the default - this was invisible: a content type is in its own related set, so every purge wildcards its own routes and the entry went anyway. With clearRelatedCache off, the action reported success and the open entry stayed cached. Send `id: documentId`, the same scope the document service middleware already uses for its own purges, and keep the other scalar fields so a custom route such as `/:slug` is still narrowed to this entry. Single types still send no params and wildcard. The e2e spec asserts the request body as well as the resulting MISS, so it fails on the old code under the default config too, not only with CLEAR_RELATED_CACHE=false.
7 of 8 tasks
The routes reference showed `"params": { "id": 42 }`. A REST route's `:id` is the documentId, so a numeric id builds a pattern no cache key matches - the same mistake the edit-view action made. The purging guide already used a documentId in its example; both now say so in the field description.
This was referenced Oct 13, 2026
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.
What changed and why
Two small bugs in the admin panel's purge controls. Both are browser-only, so neither was visible to the jest suite.
1. The edit-view "Purge REST Cache" action did not purge the entry it was opened on
useCachedDocumentbuilt the purge params from the document's own scalar fields (toPurgeParams(document)). In Strapi 5 a document'sidfield is the numeric database row id, but a REST route's:idis the documentId -/api/articles/:idis requested and cached as/api/articles/<documentId>. So the action posted{"contentType":"api::article.article","params":{"id":1,"documentId":"qwvh…","title":"…"},"wildcard":false}and
getRouteRegExpturned that into^/api/articles/1\?, which matches no cache key.Why nobody noticed: with
clearRelatedCache: true(the default) a content type is a member of its own related set, so every purge also wildcards its own routes and the entry goes anyway. WithclearRelatedCache: falsethe action showed "Cache purged successfully" and the open entry stayed cached - which contradictsdocs/guide/invalidation/purging.md("More actions → Purge REST Cache | The entry you have open").Fix: keep the scalar fields (so a custom route like
/api/articles/:slugis still narrowed to this entry) and setidto thedocumentId. That is the same scope the server's document service middleware already uses for its own purges ({ id: documentId }inregisterDocumentServiceMiddleware.ts). Single types are unchanged: no params, wildcard.2. The list-view purge button could only be used once per page load
PurgeCacheButtonsetisLoadingwhen a purge started and never cleared it. The button stays mounted after the dialog closes, so the second time the dialog opened, its confirm button was a disabled spinner and the only way out was Cancel, until a reload remounted the component.Fix:
setIsLoading(false)in thefinallythat already closes the dialog, so success and failure both leave the control usable.Why this is not breaking
Cache-Control, or what is bypassed.clearRelatedCache: truethe set of keys removed is a superset of before. The related-type wildcard still runs, and now the entry's own key is matched as well. WithclearRelatedCache: falsethe purge now removes the keys for the open entry, which is what the action and the docs say it does. Nothing that used to be purged stops being purged.Tests
New
e2e/tests/purge-controls.spec.ts:/api/articles/<documentId>from a cookie-less client, purges from the edit view, and requires aMISSafterwards. It also asserts the request body'sparams.idis the documentId. That second assertion matters: under the defaultclearRelatedCache: truetheMISSalone would pass for the wrong reason, so the body check is what fails on the old code in the normal suite.Both were run against unfixed
mainfirst and seen failing.Before, with
CLEAR_RELATED_CACHE=false:Before, default config (
clearRelatedCache: true): the MISS passes because the entry is masked by the related-type wildcard, and the body assertion catches it:After, with
CLEAR_RELATED_CACHE=false:Closes #
Checklist
shared/tests/that fails before the change. Browser-visible behaviour goes ine2e/tests/. (Both bugs are browser-only; specs are ine2e/tests/.)pnpm run test:e2e:memorypasses. (23 suites, 135 tests)pnpm run test:lintpasses (tsc --noEmitoverserver/andadmin/, plus eslint and prettier on the providers).admin/?pnpm run test:adminwas run and passes. (15 passed, default config)docs/guide/updated in this PR.docs/guide/invalidation/purging.mdalready said the edit-view action purges "the entry you have open", and this makes that true. A third commit correctsreference/routes.md, whosePOST /rest-cache/purgeexample used"params": { "id": 42 }. That is the same numeric-id mistake. Both guides now sayidis the documentId.main.Notes for the reviewer