Skip to content

Remote functions: form.action throws Cannot access event.url in a query after await query() in WebContainer / StackBlitz #16818

Description

@janekprange

Describe the bug

On a WebContainer runtime (StackBlitz), a page that awaits a remote query() and then renders a remote form() in the same SSR pass throws:

Error: Cannot access event.url in a query. Pass the value as an argument to the query instead

No user code reads event.url. Kit's form.action getter does, to build the ?/remote=… action:

// packages/kit/src/runtime/app/server/remote/form.js
get: () => {
	const search = new URLSearchParams(get_request_store().event.url.search); // <- throws
	...
}

That read is guarded to throw while a query is running (is_in_remote_query):

// packages/kit/src/runtime/app/server/remote/shared.js
if (state.is_in_remote_query) {
  for (const property of ["url", "params", "route"]) {
    Object.defineProperty(derived, property, {
      get() {
        throw new Error(
          `Cannot access event.${property} in a query. Pass the value as an argument to the query instead`,
        );
      },
    });
  }
}

Normally the query's request store is scoped to the query callback and cleared afterward, so the later form.action read sees the page's store (is_in_remote_query === false). In a WebContainer the ambient store is a module global that is never reset on purpose:

// packages/kit/src/exports/internal/server/event.js
export function with_request_store(store, fn) {
  try {
    sync_store = store;
    return als ? als.run(store, fn) : fn();
  } finally {
    // Since AsyncLocalStorage is not working in webcontainers, we don't reset `sync_store`
    // and handle only one request at a time in `src/runtime/server/index.js`.
    if (!IN_WEBCONTAINER) {
      sync_store = null;
    }
  }
}
// IN_WEBCONTAINER = !!globalThis.process?.versions?.webcontainer

After await getData() returns, sync_store still points at the query's store (is_in_remote_query === true) and is never restored. When the component then renders <form {...myForm}>, form.action → get_request_store().event.url hits that leftover query store and throws. Under export const csr = false this happens during pure SSR, so the page 500s.

On a runtime with real AsyncLocalStorage (normal Node) the finally resets sync_store and ALS scopes the store to the query callback. Same code renders fine there. This only reproduces in WebContainer / StackBlitz as far as I can see.

Reproduction

Minimal case: a .remote.ts with a query and a form, plus a page that awaits the query then renders the form.

// src/routes/data.remote.ts
import { query, form } from "$app/server";

export const getData = query(() => ({ title: "Ada" }));
export const save = form("unchecked", async () => {});
<!-- src/routes/+page.svelte -->
<script lang="ts">
	import { getData, save } from './data.remote';
	const data = await getData(); // top-level await (Svelte experimental.async)
</script>

<form {...save}>
	<!-- rendering the form reads form.action -> event.url -->
	<input {...save.fields.title.as('text', data.title)} />
	<button>Save</button>
</form>

Needs experimental.async (Svelte compiler) and experimental.remoteFunctions (Kit). Add export const csr = false; in +page.ts to force pure SSR, then it 500s every time on StackBlitz. On local Node it returns 200.

Existing repro that hits this: any no-js (csr = false) route in
https://github.com/janekprange/sveltekit-remote-form-post-success-rehydrate
500s on StackBlitz (500 GET /default/no-js) but works locally on Node.

Logs

Error: Cannot access event.url in a query. Pass the value as an argument to the query instead
    at eval (src/lib/SettingsForm.svelte:122:67)
500 GET /default/no-js

System Info

Binaries:
  Node: 25.2.1
  pnpm: 10.31.0
npmPackages:
  @sveltejs/adapter-auto: next => 8.0.0-next.3
  @sveltejs/kit: next => 3.0.0-next.23
  @sveltejs/vite-plugin-svelte: ^7.2.0 => 7.3.0
  svelte: ^5.56.7 => 5.56.9
  vite: ^8.1.5 => 8.2.1


Only reproduces on WebContainer runtimes (StackBlitz). Same code is fine on a normal Node runtime (dev and production build).

Severity

serious, but I can work around it

Additional Information

Related:

Activity

  1. added theissue type on Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    formsStuff relating to forms and form actions

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions