📑

Remixは404ページで最大3つもログを出す

2024/08/31に公開

Remixのプロジェクトを作成した直後に、開発環境で404になるページにアクセスすると以下のログが出力されます。

Error: No route matches URL "/foo" <-- (1)
    at getInternalRouterError (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+router@1.15.1/node_modules/@remix-run/router/dist/router.cjs.js:4501:59)
    at Object.query (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+router@1.15.1/node_modules/@remix-run/router/dist/router.cjs.js:3331:19)
    at handleDocumentRequestRR (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+server-runtime@2.7.0_typescript@5.5.4/node_modules/@remix-run/server-runtime/dist/server.js:184:35)
    at requestHandler (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+server-runtime@2.7.0_typescript@5.5.4/node_modules/@remix-run/server-runtime/dist/server.js:108:24)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async nodeHandler (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+dev@2.7.0_@remix-run+serve@2.7.0_typescript@5.5.4_vite@5.4.2/node_modules/@remix-run/dev/dist/vite/plugin.js:736:27)
    at async /home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+dev@2.7.0_@remix-run+serve@2.7.0_typescript@5.5.4_vite@5.4.2/node_modules/@remix-run/dev/dist/vite/plugin.js:739:15
No routes matched location "/foo"  <-- (2)
ErrorResponseImpl { <-- (3)
  status: 404,
  statusText: 'Not Found',
  internal: true,
  data: 'Error: No route matches URL "/foo"',
  error: Error: No route matches URL "/foo"
      at getInternalRouterError (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+router@1.15.1/node_modules/@remix-run/router/dist/router.cjs.js:4501:59)
      at Object.query (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+router@1.15.1/node_modules/@remix-run/router/dist/router.cjs.js:3331:19)
      at handleDocumentRequestRR (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+server-runtime@2.7.0_typescript@5.5.4/node_modules/@remix-run/server-runtime/dist/server.js:184:35)
      at requestHandler (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+server-runtime@2.7.0_typescript@5.5.4/node_modules/@remix-run/server-runtime/dist/server.js:108:24)
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
      at async nodeHandler (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+dev@2.7.0_@remix-run+serve@2.7.0_typescript@5.5.4_vite@5.4.2/node_modules/@remix-run/dev/dist/vite/plugin.js:736:27)
      at async /home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+dev@2.7.0_@remix-run+serve@2.7.0_typescript@5.5.4_vite@5.4.2/node_modules/@remix-run/dev/dist/vite/plugin.js:739:15
}

だいぶ長いエラーのように見えますが、<--で示している通り別々の3つのログが連続して表示されています。今回はそれぞれが出力される要因について調べました。

なお、この記事に書いている内容はここにほぼ同じことが書いています。

https://github.com/remix-run/remix/issues/9473#issuecomment-2127211524

(1) Error: No route matches URL "/foo"

Error: No route matches URL "/foo"
    at getInternalRouterError (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+router@1.15.1/node_modules/@remix-run/router/dist/router.cjs.js:4501:59)
    at Object.query (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+router@1.15.1/node_modules/@remix-run/router/dist/router.cjs.js:3331:19)
    at handleDocumentRequestRR (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+server-runtime@2.7.0_typescript@5.5.4/node_modules/@remix-run/server-runtime/dist/server.js:184:35)
    at requestHandler (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+server-runtime@2.7.0_typescript@5.5.4/node_modules/@remix-run/server-runtime/dist/server.js:108:24)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async nodeHandler (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+dev@2.7.0_@remix-run+serve@2.7.0_typescript@5.5.4_vite@5.4.2/node_modules/@remix-run/dev/dist/vite/plugin.js:736:27)
    at async /home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+dev@2.7.0_@remix-run+serve@2.7.0_typescript@5.5.4_vite@5.4.2/node_modules/@remix-run/dev/dist/vite/plugin.js:739:15

表示される原因

サーバー側でエラーが発生した際にremixがログを出力するためです。実装はこのあたりでした。

https://github.com/remix-run/remix/blob/8f38118e44298d609224c6074ae6519d385196f1/packages/remix-server-runtime/server.ts#L459-L467
https://github.com/remix-run/remix/blob/8f38118e44298d609224c6074ae6519d385196f1/packages/remix-server-runtime/server.ts#L69-L78

表示させない方法

この関数はentry.server.tsxでhandleErrorという関数を定義すると動作を上書きできます。公式ドキュメントはこちら。

https://remix.run/docs/en/main/file-conventions/entry.server#handleerror

以下のような感じで実装すると良さそうです。

export function handleError(
  error: unknown,
  { request }: LoaderFunctionArgs | ActionFunctionArgs,
) {
  if (
    (isRouteErrorResponse(error) && error.status === 404) ||
    request.signal.aborted
  ) {
    return;
  }
  console.error(error);
}

リクエストが中止された時はログを出さない方が良いとのことなので、request.signal.abortedも見ています。

Note that you generally want to avoid logging when the request was aborted, since Remix's cancellation and race-condition handling can cause a lot of requests to be aborted.
https://remix.run/docs/en/main/file-conventions/entry.server#handleerror

(2) No routes matched location "/foo"

No routes matched location "/foo" 

表示される原因

react-routerが一致しないルートに対してログを出力しているためです。実装はこれ。

https://github.com/remix-run/react-router/blob/9afac15d8cbe30b37d0f9e8b89c9f1e430dfe35a/packages/react-router/lib/hooks.tsx#L450-L454

表示させない方法

開発環境でのみ出るログのようなので、本番環境では出ません。設定不要。

(3) ErrorResponseImpl

ErrorResponseImpl {
  status: 404,
  statusText: 'Not Found',
  internal: true,
  data: 'Error: No route matches URL "/foo"',
  error: Error: No route matches URL "/foo"
      at getInternalRouterError (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+router@1.15.1/node_modules/@remix-run/router/dist/router.cjs.js:4501:59)
      at Object.query (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+router@1.15.1/node_modules/@remix-run/router/dist/router.cjs.js:3331:19)
      at handleDocumentRequestRR (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+server-runtime@2.7.0_typescript@5.5.4/node_modules/@remix-run/server-runtime/dist/server.js:184:35)
      at requestHandler (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+server-runtime@2.7.0_typescript@5.5.4/node_modules/@remix-run/server-runtime/dist/server.js:108:24)
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
      at async nodeHandler (/home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+dev@2.7.0_@remix-run+serve@2.7.0_typescript@5.5.4_vite@5.4.2/node_modules/@remix-run/dev/dist/vite/plugin.js:736:27)
      at async /home/ubuntu/playground/remix-404-error/node_modules/.pnpm/@remix-run+dev@2.7.0_@remix-run+serve@2.7.0_typescript@5.5.4_vite@5.4.2/node_modules/@remix-run/dev/dist/vite/plugin.js:739:15
}

表示される原因

RemixがReactでのエラーに対してErrorBoundaryを表示する時にログを表示するためです。実装は多分これです。

https://github.com/remix-run/remix/blob/8f38118e44298d609224c6074ae6519d385196f1/packages/remix-react/errorBoundaries.tsx#L72-L79

表示させない方法

ErrorBoundaryという名前でルートファイルからコンポーネントをexportするとデフォルトの挙動を上書きできます。root.tsxなどに適当な内容で作成しましょう。

https://remix.run/docs/en/main/route/error-boundary

まとめ

  • entry.server.tsxにhandleErrorを書く
  • root.tsxにErrorBoundaryを書く
  • 本番環境にする

以上でログを抑えられます。Issueへのメンテナからのコメントを見る限り意図した挙動のようですが、ちょっと分かりにくいと思いました。

404ページでのエラーログが煩わしくなってきた時は参考にしてみてください。

GitHubで編集を提案

Discussion