{"record":{"id":"067acde6258d9ff9","repo":"facebook/react","slug":"symbols-cannot-be-passed-to-a-server-function-with","errorCode":null,"errorMessage":"Symbols cannot be passed to a Server Function without a temporary reference set. Pass a TemporaryReferenceSet to the options.","messagePattern":"Symbols cannot be passed to a Server Function without a temporary reference set\\. Pass a TemporaryReferenceSet to the options\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-client/src/ReactFlightReplyClient.js","lineNumber":866,"sourceCode":"        'Client Functions cannot be passed directly to Server Functions. ' +\n          'Only Functions passed from the Server can be passed back again.',\n      );\n    }\n\n    if (typeof value === 'symbol') {\n      if (temporaryReferences !== undefined && key.indexOf(':') === -1) {\n        // TODO: If the property name contains a colon, we don't dedupe. Escape instead.\n        const parentReference = writtenObjects.get(parent);\n        if (parentReference !== undefined) {\n          // If the parent has a reference, we can refer to this object indirectly\n          // through the property name inside that parent.\n          const reference = parentReference + ':' + key;\n          // Store this object so that the server can refer to it later in responses.\n          writeTemporaryReference(temporaryReferences, reference, value);\n          return serializeTemporaryReferenceMarker();\n        }\n      }\n      throw new Error(\n        'Symbols cannot be passed to a Server Function without a ' +\n          'temporary reference set. Pass a TemporaryReferenceSet to the options.' +\n          (__DEV__ ? describeObjectForErrorMessage(parent, key) : ''),\n      );\n    }\n\n    if (typeof value === 'bigint') {\n      return serializeBigInt(value);\n    }\n\n    throw new Error(\n      `Type ${typeof value} is not supported as an argument to a Server Function.`,\n    );\n  }\n\n  function serializeModel(model: ReactServerValue, id: number): string {\n    if (typeof model === 'object' && model !== null) {\n      const reference = serializeByValueID(id);","sourceCodeStart":848,"sourceCodeEnd":884,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react-client/src/ReactFlightReplyClient.js#L848-L884","documentation":"Symbols have no wire representation in the Flight reply format, so a symbol argument can only be sent by registering it in a TemporaryReferenceSet that the server shares. If temporaryReferences is undefined (or the symbol is not reachable via a dedupe-able parent path), serializeReply throws, naming the missing option. The same constraint applies to symbol values anywhere in the argument tree, not just at the top level.","triggerScenarios":"Passing a symbol as a Server Function argument or inside one: await setTheme(SYMBOLS.dark); library objects that internally use symbol keys/values (registries, well-known symbols) leaking into the payload without a temporaryReferences set.","commonSituations":"Sending theme/feature tokens implemented as symbols; styling libraries that key slots with symbols; enum-like symbols shared between client and server code; forgetting the options object entirely when hand-rolling encodeReply.","solutions":["Pass a TemporaryReferenceSet in the encodeReply/callServer options so symbols can be registered and referenced by id","Send a string instead: symbol.description or a stable registry key, and rebuild the symbol on the server from a shared table","Audit argument trees for symbols before sending (typeof v === 'symbol') and map them explicitly","If the symbol is only used as a property key locally, restructure to plain string keys for data that crosses the boundary"],"exampleFix":"// before\nconst THEMES = {dark: Symbol('dark'), light: Symbol('light')};\nawait setTheme(THEMES.dark); // throws\n\n// after\nawait setTheme('dark'); // string token; server maps it back to its own symbol","handlingStrategy":"validation","validationCode":"// Reject or map symbols before the call crosses the boundary\nfunction assertNoBareSymbols(v: unknown, seen = new Set()): void {\n  if (typeof v === 'symbol') {\n    throw new Error('Symbol argument requires a TemporaryReferenceSet - or send a string token');\n  }\n  if (v === null || typeof v !== 'object' || seen.has(v)) return;\n  seen.add(v);\n  Object.values(v).forEach(c => assertNoBareSymbols(c, seen));\n}","typeGuard":"const isSymbol = (v: unknown): v is symbol => typeof v === 'symbol';","tryCatchPattern":null,"preventionTips":["Use string tokens instead of symbols for anything crossing the network","If symbols are required, always call with a TemporaryReferenceSet in the options","Audit library objects for internal symbol usage before forwarding them to server actions"],"tags":["server-functions","serialization","symbols","rsc","temporary-references"],"backgroundTag":"non-serializable-argument","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}