{"record":{"id":"ff7dbea9e9fd9091","repo":"sveltejs/kit","slug":"promises-are-not-valid-remote-function-arguments","errorCode":null,"errorMessage":"Promises are not valid remote function arguments","messagePattern":"Promises are not valid remote function arguments","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/kit/src/runtime/shared.js","lineNumber":297,"sourceCode":"\t\t\t\tname: value.name,\n\t\t\t\tsize: value.size,\n\t\t\t\ttype: value.type\n\t\t\t}));\n\n\t\t\tallowed_promises.add(promise);\n\n\t\t\treturn promise;\n\t\t}\n\t};\n\n\t// we don't want to allow arbitrary promises, because they won't\n\t// show up as promises on the other side. this is something\n\t// we could potentially change in future. stringifyAsync\n\t// will await them, so we need to explicitly deny them\n\t/** @param {unknown} value */\n\treducers[remote_promise_guard] = (value) => {\n\t\tif (value instanceof Promise && !allowed_promises.has(value)) {\n\t\t\tthrow new Error('Promises are not valid remote function arguments');\n\t\t}\n\t};\n\n\tconst json = await devalue.stringifyAsync(value, reducers);\n\n\treturn url_friendly_base64_encode(json);\n}\n\n/**\n * Base64-encodes `string` in such a way that the result is safe to use\n * as both a URI component and a filename\n * @param {string} string\n */\nfunction url_friendly_base64_encode(string) {\n\tconst bytes = text_encoder.encode(string);\n\t// TODO replace with `bytes.toBase64({ alphabet: 'base64url', omitPadding: true })` when we require Node >= 25\n\treturn base64_encode(bytes).replaceAll('=', '').replaceAll('+', '-').replaceAll('/', '_');\n}","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/runtime/shared.js#L279-L315","documentation":"Remote function arguments are serialized with devalue.stringifyAsync. devalue would silently await promises, turning them into plain resolved values on the other side — which is not what callers expect. SvelteKit therefore explicitly rejects any Promise in the argument graph unless it is an internally generated one (from a File's arrayBuffer()).","triggerScenarios":"Passing a Promise (or an object/array containing one) as an argument to a remote function, e.g. `remoteFn(fetch('/api/data'))`, `remoteFn(someAsync())`, or a value returned from an async helper that you forgot to await.","commonSituations":"Forgetting `await` on an async function's result before passing it to a remote `.query()`/`.command()`; passing a fetch() response promise; passing reactive state that wraps a promise (e.g. from an async derived).","solutions":["Await the promise before passing it: `remoteFn(await someAsync())`","If you need async data, fetch it inside the remote function itself, not in the caller","Pass a plain serializable value instead of the promise result's wrapper","If a Svelte store/derived yields a promise, resolve it before sending (e.g. in an effect or with await)"],"exampleFix":"// before\nconst res = fetch('/api/data');\nawait updateUser(res);\n// after\nconst res = await fetch('/api/data');\nawait updateUser(await res.json());","handlingStrategy":"type-guard","validationCode":"function assertSerializable(value, seen = new Set()) {\n  if (value instanceof Promise) throw new Error('Promise passed to remote function — await it first');\n  if (value && typeof value === 'object' && !seen.has(value)) {\n    seen.add(value);\n    Object.values(value).forEach((v) => assertSerializable(v, seen));\n  }\n  return value;\n}","typeGuard":"const isThenable = (v) => !!v && typeof v === 'object' && typeof v.then === 'function';","tryCatchPattern":"try {\n  await remoteFn(arg);\n} catch (e) {\n  if (e.message === 'Promises are not valid remote function arguments') {\n    throw new Error('You forgot to await a value before passing it to a remote function');\n  }\n  throw e;\n}","preventionTips":["Await async results before passing them to remote functions","Use TypeScript so passing a Promise where a JSON-serializable type is expected errors at compile time","Lint rules (no-floating-promises) help catch un-awaited values","Move async fetching into the remote function itself when possible"],"tags":["remote-functions","async","serialization"],"backgroundTag":"promise-passed-to-remote-function","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}