{"record":{"id":"0bf9380288b40eb7","repo":"vercel/next.js","slug":"error-serializing-path-returned-from-metho","errorCode":null,"errorMessage":"Error serializing `${path}` returned from `${method}` in \"${page}\".\nReason: Circular references cannot be expressed in JSON (references: `${visited.get(value) || '(self)'}`).","messagePattern":"Error serializing `(.+?)` returned from `(.+?)` in \"(.+?)\"\\.\nReason: Circular references cannot be expressed in JSON \\(references: `(.+?)`\\)\\.","errorType":"exception","errorClass":"SerializableError","httpStatus":null,"severity":"error","filePath":"packages/next/src/lib/is-serializable-props.ts","lineNumber":36,"sourceCode":"export function isSerializableProps(\n  page: string,\n  method: string,\n  input: any\n): true {\n  if (!isPlainObject(input)) {\n    throw new SerializableError(\n      page,\n      method,\n      '',\n      `Props must be returned as a plain object from ${method}: \\`{ props: { ... } }\\` (received: \\`${getObjectClassLabel(\n        input\n      )}\\`).`\n    )\n  }\n\n  function visit(visited: Map<any, string>, value: any, path: string) {\n    if (visited.has(value)) {\n      throw new SerializableError(\n        page,\n        method,\n        path,\n        `Circular references cannot be expressed in JSON (references: \\`${\n          visited.get(value) || '(self)'\n        }\\`).`\n      )\n    }\n\n    visited.set(value, path)\n  }\n\n  function isSerializable(\n    refs: Map<any, string>,\n    value: any,\n    path: string\n  ): true {\n    const type = typeof value","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/lib/is-serializable-props.ts#L18-L54","documentation":"Thrown by isSerializableProps() when, during deep traversal of the props object, a value is encountered that already exists in the visited Map — i.e. a circular reference. JSON cannot express cycles, so Next.js reports the first path that closed the loop (or '(self)' if it points to its own path).","triggerScenarios":"A getStaticProps/getServerSideProps return value contains an object that references itself (directly or transitively). The visit() function tracks each object/array by path; re-encountering one throws with the original path that referenced it.","commonSituations":"Bidirectional ORM relations (user.posts[].user); manually linking nodes in a tree; caching an object and reusing the same reference in multiple places that form a cycle; or building a graph data structure in props.","solutions":["Break the cycle before returning: map bidirectional relations to one direction only, or replace back-references with IDs.","Use a safe stringify or selective picker (e.g. only expose whitelisted fields) to flatten the graph into a tree.","Sanitize with JSON.parse(JSON.stringify(props)) to drop cyclic references before returning.","Unit test data-fetching functions against a serialize check."],"exampleFix":"// before\nexport async function getStaticProps() {\n  const post = await getPost(id)\n  post.author.posts = [post] // circular: post -> author -> post\n  return { props: { post } }\n}\n// after\nexport async function getStaticProps() {\n  const post = await getPost(id)\n  return {\n    props: {\n      post: { ...post, author: { name: post.author.name } } // no back-ref\n    },\n  }\n}","handlingStrategy":"validation","validationCode":"function hasCycle(obj: unknown): boolean {\n  const seen = new WeakSet()\n  function visit(v: unknown): boolean {\n    if (v && typeof v === 'object') {\n      if (seen.has(v)) return true\n      seen.add(v)\n      return Object.values(v).some(visit)\n    }\n    return false\n  }\n  return visit(obj)\n}\n// if (hasCycle(props)) throw new Error('circular props')","typeGuard":"function isAcyclic(v: unknown, seen = new WeakSet()): boolean {\n  if (v && typeof v === 'object') {\n    if (seen.has(v)) return false\n    seen.add(v)\n    return Object.values(v).every((c) => isAcyclic(c, seen))\n  }\n  return true\n}","tryCatchPattern":null,"preventionTips":["Avoid bidirectional ORM relations in props; reference by ID.","Build props as a fresh plain object, selecting fields explicitly.","Sanitize with JSON.parse(JSON.stringify(props)) to drop unserializable/cyclic refs before returning.","Unit test data-fetching functions against a serialize check."],"tags":["serialization","getstaticprops","getserversideprops","build","data-fetching"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}