What happens
During Site Editor startup, @wordpress/core-data can request OPTIONS /wp/v2/settings multiple times for the same logical metadata:
- root
site entity config/schema loading fetches OPTIONS /wp/v2/settings
- later
canUser( ..., { kind: 'root', name: 'site' } ) fetches OPTIONS /wp/v2/settings again for permissions
That first OPTIONS response already has the Allow header needed to seed the canUser permission cache, but the root site entity loader only uses the schema labels.
Why this matters
This makes REST preloading look incomplete even when the server declares the right preload path. The first client request consumes the single-use preload entry, then the later permission request falls through to network.
In Site Editor profiling this leaves an avoidable startup REST request:
OPTIONS /wp/v2/settings?_locale=user
Proof
I added a failing regression test in a local proof worktree:
/Users/chubes/Developer/gutenberg@prove-canuser-options-duplicates
packages/core-data/src/hooks/test/use-resource-permissions.js
Targeted command:
npm run test:unit -- --runTestsByPath packages/core-data/src/hooks/test/use-resource-permissions.js --runInBand
Failing test:
useResourcePermissions › reuses the root site entity schema OPTIONS response for site permissions
Expected length: 1
Received length: 3
Received array:
[
[{ method: "OPTIONS", path: "/wp/v2/settings" }],
[{ method: "OPTIONS", path: "/wp/v2/settings" }],
[{ method: "OPTIONS", parse: false, path: "/wp/v2/settings" }]
]
Profiling evidence
Homeboy Site Editor run with caller attribution:
- Run ID:
63df7a69-2f6f-4a39-9ee6-1fcf07bd449f
- Raw artifact:
/Users/chubes/Developer/_bench-evidence/homeboy-artifacts/63df7a69-2f6f-4a39-9ee6-1fcf07bd449f/8c48727c-0eac-4844-bc4b-c6fe2316c366-result-studio-site-editor-preload-comparison-17100-1778709161659-9azz7zw3074.json
Caller attribution showed both core-data paths:
OPTIONS /wp/v2/settings?_locale=user
apiFetch caller: Object.loadEntities (.../core-data.min.js...)
apiFetch caller: .../core-data.min.js... canUser resolver path
Prompting context
This came out of investigating why extra deterministic Site Editor REST preload paths still left OPTIONS /wp/v2/settings visible in DevTools/network waterfalls.
Related preload work:
Those PRs exposed the smell, but this issue is client-side core-data reuse, not a missing server preload declaration.
Likely fix direction
When loadSiteEntity() fetches OPTIONS /wp/v2/settings, it should reuse that response's Allow header to seed user permissions and mark related canUser resolutions as finished for { kind: 'root', name: 'site' }.
Alternatively, root entity schema loading and permission resolution should share a common helper so one OPTIONS response populates both schema labels and permissions.
What happens
During Site Editor startup,
@wordpress/core-datacan requestOPTIONS /wp/v2/settingsmultiple times for the same logical metadata:siteentity config/schema loading fetchesOPTIONS /wp/v2/settingscanUser( ..., { kind: 'root', name: 'site' } )fetchesOPTIONS /wp/v2/settingsagain for permissionsThat first OPTIONS response already has the
Allowheader needed to seed thecanUserpermission cache, but the root site entity loader only uses the schema labels.Why this matters
This makes REST preloading look incomplete even when the server declares the right preload path. The first client request consumes the single-use preload entry, then the later permission request falls through to network.
In Site Editor profiling this leaves an avoidable startup REST request:
Proof
I added a failing regression test in a local proof worktree:
Targeted command:
Failing test:
Profiling evidence
Homeboy Site Editor run with caller attribution:
63df7a69-2f6f-4a39-9ee6-1fcf07bd449f/Users/chubes/Developer/_bench-evidence/homeboy-artifacts/63df7a69-2f6f-4a39-9ee6-1fcf07bd449f/8c48727c-0eac-4844-bc4b-c6fe2316c366-result-studio-site-editor-preload-comparison-17100-1778709161659-9azz7zw3074.jsonCaller attribution showed both
core-datapaths:Prompting context
This came out of investigating why extra deterministic Site Editor REST preload paths still left
OPTIONS /wp/v2/settingsvisible in DevTools/network waterfalls.Related preload work:
Those PRs exposed the smell, but this issue is client-side core-data reuse, not a missing server preload declaration.
Likely fix direction
When
loadSiteEntity()fetchesOPTIONS /wp/v2/settings, it should reuse that response'sAllowheader to seed user permissions and mark relatedcanUserresolutions as finished for{ kind: 'root', name: 'site' }.Alternatively, root entity schema loading and permission resolution should share a common helper so one OPTIONS response populates both schema labels and permissions.