{"record":{"id":"084ea3b840a8bb5b","repo":"coder/code-server","slug":"not-found","errorCode":null,"errorMessage":"Not Found","messagePattern":"Not Found","errorType":"http","errorClass":"HttpError","httpStatus":404,"severity":"warning","filePath":"src/node/routes/index.ts","lineNumber":176,"sourceCode":"    app.router.use(\"/login\", login.router)\n    app.router.use(\"/logout\", logout.router)\n  } else {\n    app.router.all(\"/login\", (req, res) => redirect(req, res, \"/\", {}))\n    app.router.all(\"/logout\", (req, res) => redirect(req, res, \"/\", {}))\n  }\n\n  app.router.use(\"/update\", update.router)\n\n  // For historic reasons we also load at /vscode because the root was replaced\n  // by a plugin in v1 of Coder.  The plugin system (which was for internal use\n  // only) has been removed, but leave the additional route for now.\n  for (const routePrefix of [\"/vscode\", \"/\"]) {\n    app.router.use(routePrefix, vscode.router)\n    app.wsRouter.use(routePrefix, vscode.wsRouter.router)\n  }\n\n  app.router.use(() => {\n    throw new HttpError(\"Not Found\", HttpCode.NotFound)\n  })\n\n  app.router.use(errorHandler)\n  app.wsRouter.use(wsErrorHandler)\n\n  return {\n    disposeRoutes: () => {\n      heart.dispose()\n      vscode.dispose()\n    },\n    heart,\n  }\n}\n","sourceCodeStart":158,"sourceCodeEnd":190,"githubUrl":"https://github.com/coder/code-server/blob/51f90a376b42e217b38937410fe2855e0c1db87e/src/node/routes/index.ts#L158-L190","documentation":"The catch-all route handler (index.ts:176) runs after every registered route and throws HttpError 404 Not Found for any unmatched path, before the error handler renders the response. This guarantees a controlled 404 instead of Express's default 'cannot GET'.","triggerScenarios":"Any GET/POST/etc. to a path not matched by an earlier route: typos like /loign, removed/renamed endpoints, or stale bookmarks.","commonSituations":"Users with old bookmarks after an upgrade; clients hitting an endpoint removed in this version; crawlers probing arbitrary paths.","solutions":["Verify the URL spelling and that the route exists in this code-server version","Update bookmarks/client base URLs to the current paths","If the path is from a plugin, confirm the plugin is installed and its routes are registered"],"exampleFix":"// before\nfetch('/loign')   // 404\n\n// after\nfetch('/login')","handlingStrategy":"try-catch","validationCode":"// For clients: validate a URL is a known route before fetching\nconst KNOWN_PREFIXES = [\"/login\", \"/logout\", \"/vscode\", \"/proxy\", \"/healthz\", \"/static\"]\nfunction isLikelyKnownRoute(path: string): boolean {\n  return KNOWN_PREFIXES.some((p) => path === p || path.startsWith(p + \"/\"))\n}","typeGuard":"import { HttpError, HttpCode } from \"../../common/http\"\nfunction isNotFound(e: unknown): boolean {\n  return e instanceof HttpError && e.status === HttpCode.NotFound\n}","tryCatchPattern":"try {\n  await fetch(path)\n} catch (e) {\n  if (isNotFound(e)) {\n    // show a user-friendly 404 page or correct the URL\n    showNotFoundPage(path)\n  } else throw e\n}","preventionTips":["Maintain a list of current route prefixes for client URL builders","After upgrades, test old bookmarks and update clients for renamed routes","Treat 404 as expected in crawlers; do not alert on it"],"tags":["http","routing","not-found","middleware"],"backgroundTag":null,"analyzedSha":"51f90a376b42e217b38937410fe2855e0c1db87e","analyzedAt":"2026-08-12T11:27:34.273Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}