{"record":{"id":"14de23414ff12cac","repo":"remix-run/react-router","slug":"you-are-trying-to-call-fn-on-a-route-that-does-14de23","errorCode":null,"errorMessage":"You are trying to call ${fn} on a route that does not have a server ${type} (routeId: \"${routeId}\")","messagePattern":"You are trying to call (.+?) on a route that does not have a server (.+?) \\(routeId: \"(.+?)\"\\)","errorType":"http","errorClass":"ErrorResponseImpl","httpStatus":400,"severity":"error","filePath":"packages/react-router/lib/rsc/browser.tsx","lineNumber":1022,"sourceCode":"}\n\nfunction callSingleFetch(singleFetch: unknown) {\n  invariant(typeof singleFetch === \"function\", \"Invalid singleFetch parameter\");\n  return singleFetch();\n}\n\nfunction preventInvalidServerHandlerCall(\n  type: \"action\" | \"loader\",\n  routeId: string,\n  hasHandler: boolean,\n) {\n  if (!hasHandler) {\n    let fn = type === \"action\" ? \"serverAction()\" : \"serverLoader()\";\n    let msg =\n      `You are trying to call ${fn} on a route that does not have a server ` +\n      `${type} (routeId: \"${routeId}\")`;\n    console.error(msg);\n    throw new ErrorResponseImpl(400, \"Bad Request\", new Error(msg), true);\n  }\n}\n\n// Currently rendered links that may need prefetching\nconst nextPaths = new Set<string>();\n\n// FIFO queue of previously discovered routes to prevent re-calling on\n// subsequent navigations to the same path\nconst discoveredPathsMaxSize = 1000;\nconst discoveredPaths = new Set<string>();\n\nfunction getManifestUrl(\n  paths: string[],\n  clientVersion: string | undefined,\n): URL | null {\n  if (paths.length === 0) {\n    return null;\n  }","sourceCodeStart":1004,"sourceCodeEnd":1040,"githubUrl":"https://github.com/remix-run/react-router/blob/7aea711dd1ae2bc5a076d13ff17291829690fa74/packages/react-router/lib/rsc/browser.tsx#L1004-L1040","documentation":"In RSC mode, `serverLoader()`/`serverAction()` calls from client components are gated by `preventInvalidServerHandlerCall`, which checks the route's `hasLoader`/`hasAction` flags from the server manifest before issuing the fetch. When the flag is false it logs the message and throws an `ErrorResponseImpl(400, \"Bad Request\")`, surfacing through the nearest error boundary. It is the RSC equivalent of the framework-mode guard in routes.tsx.","triggerScenarios":"Calling `serverLoader()` in a route whose module has no `loader` export (e.g., a client-only route that assumed server data); calling `serverAction()` where only `clientAction` exists; stale manifests after adding a loader without reloading; moving a loader between routes and leaving the call behind.","commonSituations":"Converting pages to RSC and calling serverLoader from client components before wiring the server loader; hot-reload keeping an old manifest during development; renaming route files so the manifest id no longer carries the hasLoader flag.","solutions":["Add the missing `loader` (or `action`) export to the target route's module so the manifest marks it.","Restart the dev server / rebuild so the RSC manifest reflects the new handler.","If the data is fetched client-side only, stop calling `serverLoader()` and fetch directly.","Confirm you are calling it from the route whose handler you added, not a sibling/child route."],"exampleFix":"// before\n// app/routes/todo.tsx (no loader export)\n\"use client\";\nexport async function clientLoader() {\n  return await serverLoader();\n}\n\n// after\n// app/routes/todo.tsx\nexport async function loader() {\n  return { items: await getTodos() };\n}\n\"use client\";\nexport async function clientLoader() {\n  return await serverLoader();\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await serverLoader();\n} catch (e) {\n  if (isResponse(e) && e.status === 400) {\n    return fetchClientSideFallback(); // route has no server loader\n  }\n  throw e;\n}","preventionTips":["Add the server loader/action export before wiring serverLoader()/serverAction() calls.","Restart the dev server after changing route handlers so the RSC manifest updates.","Keep handler and call site in the same route module."],"tags":["rsc","server-loader","server-action","http-400"],"backgroundTag":"server-handler-not-defined","analyzedSha":"7aea711dd1ae2bc5a076d13ff17291829690fa74","analyzedAt":"2026-08-18T18:04:14.938Z","contentChangedAt":"2026-08-18T18:04:14.938Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}