Remote functions incorrectly send full response to client when used in server loads
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 20.8k
- Forks
- 2.3k
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 156
Description
Describe the bug
When using a remote function within a server load, the entire payload of the remote function is sent to the client, no matter which properties you actually intend to send.
This probably isn't a security issue, as generally remote functions are called from the client anyway, but it could be unwanted behavior and could expose data that wasn't supposed to be exposed.
In my situation, I simply wanted to reuse the same remote function but only expose a handful of properties instead of the full payload.
Here's a setup:
// query.remote.ts
import { query } from "$app/server";
export const getSomeData = query(async () => {
return { message: "Hello!", bigData: "x".repeat(10000) };
});
// +page.server.ts
import { getSomeData } from '$lib/query.remote';
import type { PageServerLoad } from './$types';
export const load = (async () => {
const data = await getSomeData();
return {
message: data.message,
};
}) satisfies PageServerLoad;
+page.svelte (slightly longer but basically does nothing)
<script lang="ts">
import { onMount } from "svelte";
import type { PageProps } from "./$types";
let { data }: PageProps = $props();
let scriptContent = $state("");
onMount(() => {
// Select the script tag in the body
const scriptTag = document.querySelector("script");
scriptContent = (scriptTag?.innerHTML || "");
});
</script>
<h1>Welcome to SvelteKit</h1>
<p>
Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the
documentation
</p>
<p>{data.message}</p>
<p>Check the HTML for "bigData" that has a ton of x's repeated. This wasn't supposed to be sent to the client.</p>
<p>Contents of script tag:</p>
<p>{scriptContent}</p>
Despite only passing down message, the full payload is sent to the client and can be seen in the HTML. The attached reproduction shows the contents of the script tag that sveltekit generates, and you can see the 10,000 "x"s in the html:
Expected Behavior
I thought using remote functions on the server like this would just grab the data being returned like a normal function call. For the example, the page server load should effectively behave like this:
export const load = (async () => {
const data = { message: "Hello!", bigData: "x".repeat(10000) };
return {
message: data.message,
};
}) satisfies PageServerLoad;
Which, as expected, only sends message to the client.
Reproduction
Reproduction:
remote-functions-in-load.zip
or
https://stackblitz.com/edit/sveltejs-kit-template-default-5uwyw2aw?file=src%2Flib%2Fquery.remote.ts
Simply load the main page to see that the full response is sent to the client, even though only message was passed down.
Logs
System Info
System:
OS: Windows 10 10.0.19045
CPU: (16) x64 AMD Ryzen 7 9800X3D 8-Core Processor
Memory: 3.44 GB / 31.16 GB
Binaries:
Node: 24.6.0 - C:\nvm4w\nodejs\node.EXE
Yarn: 1.22.22 - C:\nvm4w\nodejs\yarn.CMD
npm: 11.5.1 - C:\nvm4w\nodejs\npm.CMD
pnpm: 10.15.0 - C:\nvm4w\nodejs\pnpm.CMD
Browsers:
Edge: Chromium (140.0.3485.54)
Internet Explorer: 11.0.19041.5794
npmPackages:
@sveltejs/adapter-auto: ^6.0.0 => 6.1.0
@sveltejs/kit: ^2.22.0 => 2.42.1
@sveltejs/vite-plugin-svelte: ^6.0.0 => 6.2.0
svelte: ^5.0.0 => 5.38.10
vite: ^7.0.4 => 7.1.5
Severity
annoyance
Additional Information
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the linked reproduction and inspect query.remote.ts, +page.server.ts, and the generated script from +page.svelte. Trace how a remote function called during a server load is serialized into page data. Done means the page still receives message while bigData is absent from the client HTML, with regression coverage for this case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100