Repository navigation
Cued-up query .refresh()es in commands not deferred until operation is complete #16202
Description
Activity
Although I welcome the idea of refreshed queries being queued and deferred to the end of a
command(or otherquery's) function scope, this feels a bit magic or less deterministic than refreshing queries after a mutation ends.For example:
export const increment_state = command(async () => { - get_state().refresh(); await new Promise(res => setTimeout(res, 1000)); state++; + get_state().refresh(); });Here, the mutation has completed successfully and we know it's safe to refresh the query because we're definitely sure the data will be fresh. This is particularly readable when performing error handling for an async mutation. Maybe if there were a
.deferredRefresh()method name, it would more intuitively describe its behaviour.I had run this by Rich first in Discord, and he said that what I described here was what he believed he intended the behavior to be.
elliott-with-the-longest-name-on-github commented
on Jun 30, 2026 ContributorMore actionsYeah this is indeed how it's already supposed to work
I've ran into issues with refreshes in commands before and opened #14877 a while ago because of a similar issue.
If this behaviour were actually implemented as in this bug report you'd end up with stale values if you depend on the query data itself during the command, so having refresh not actually do the refresh feels wrong to me.
export const addTodo = command(async (todo) => { const todos = await getTodos(); // save todos to a JSON field in a db that requires all old todos, not just a simple insert await getTodos().refresh(); // refresh both server cache AND single flight mutation return (await getTodos()).length });
The fact that the promise of refresh is not awaiting the actual request is a regression already IMO. I am aware that it was a deliberate choice so that multiple awaited refreshes don't cause a waterfall, but that's what
Promise.allis for, I definitely agree with @theetrain that sveltekit should stay predictable with the mental model of Javascript itself.elliott-with-the-longest-name-on-github commented
on Jul 1, 2026 ContributorMore actionsActually I think the implementation would work just fine.
refreshwill immediately invalidate the request cache but won't actually kick off the refresh until after the command finishes. So the next call togetTodoswill return the new data and populate the cache.refreshbasically means "invalidate, mark this as a single flight mutation, and if we don't have a cache value at the end of this command, populate the cache".Reacted by Philip BreuerIt certainly won't hurt having this behaviour; we could call
.refresh()at the top or bottom of a function and there wouldn't be a race condition concern, so people may choose whichever placement they prefer.It's definitely worth documenting these behaviours, especially if
.refresh()is different when called server-side or browser-side.- linked a pull request that will close this issuefix: defer `refresh` until after command #16225
on Jul 3, 2026
Describe the bug
If you run a
some_query().refresh()during a remote function command, it should cue up the refresh but only kick it off once the command finishes. Instead it appears that it starts the refresh immediately. If it takes a while before the state change happens that would have changed the response of that query, the server-driven refresh can return an outdated value.Reproduction
state.remote.js:Pressing the 'increment' button leaves the 'state' counter one click behind what it actually is. Refreshing the page again changes it once more to be the correct value.
Logs
System Info
System: OS: Linux 6.18 Ubuntu 26.04 LTS 26.04 (Resolute Raccoon) CPU: (8) x64 Intel(R) Core(TM) Ultra 7 258V Memory: 10.33 GB / 15.39 GB Container: Yes Shell: 5.3.9 - /bin/bash Binaries: Node: 26.4.0 Yarn: 1.22.22 npm: 11.17.0 pnpm: 11.9.0 npmPackages: @sveltejs/adapter-auto: ^7.0.1 => 7.0.1 @sveltejs/kit: ^2.63.0 => 2.68.0 @sveltejs/vite-plugin-svelte: ^7.1.2 => 7.1.2 svelte: ^5.56.1 => 5.56.4 vite: ^8.0.16 => 8.1.0Severity
annoyance
Additional Information
No response