Next.jsのAPI RoutesでTypeError: Failed to parse URL fromエラーが出る

# はじめに

おなじみのエラーですが、初めて遭遇したパターンだったのでまとめていきます。

# 問題

以下のAPIを作成しました。

```ts:pages/api/hello.ts
import supabase from '@/app/utils/supabase'
import type { NextApiRequest, NextApiResponse } from 'next'

type StudyRecord = {
  title: string
  time: number
}

type StudyRecordData = {
  id: number
  title: string
  time: number
  created_at: string
}
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {

  if (req.method === 'POST') {
    const { title, time } = req.body

    const { error } = await supabase.from('study-record').insert([
      { title, time }
    ])

    if (error) {
      return res.status(500).json({ message: error.message })
    }

    return res.status(200).json({ message: 'success' })
  } else if (req.method === 'GET') {

    const {data, error } = await supabase.from('study-record').select('*')

    if (error) {
      return res.status(500).json({ message: error.message })
    }

    const studyRecords: StudyRecord[] = data.map((record: StudyRecordData) => {
      return {
        title: record.title,
        time: record.time
      }
    })

    res.status(200).json({ studyRecords })
  }

}
```

ここで起動すると問題なくAPIは使えます。

そして以下のコマンドを叩くとエラーが発生しました

```
$ npm run build
```


```
TypeError: Failed to parse URL from /api/hello
    at Object.fetch (node:internal/deps/undici/undici:13220:11)
    at async p (/home/jinwatanabe/workspace/tmp/env-test/.next/server/pages/add.js:1:740) {
  [cause]: TypeError: Invalid URL
      at new URL (node:internal/url:775:36)
      at new Request (node:internal/deps/undici/undici:7173:25)
      at fetch2 (node:internal/deps/undici/undici:11161:25)
      at Object.fetch (node:internal/deps/undici/undici:13218:18)
      at fetch (node:internal/process/pre_execution:282:25)
      at p (/home/jinwatanabe/workspace/tmp/env-test/.next/server/pages/add.js:1:746)
      at renderWithHooks (/home/jinwatanabe/workspace/tmp/env-test/node_modules/react-dom/cjs/react-dom-server.edge.production.js:4184:18)
      at renderElement (/home/jinwatanabe/workspace/tmp/env-test/node_modules/react-dom/cjs/react-dom-server.edge.production.js:4322:14)
      at retryNode (/home/jinwatanabe/workspace/tmp/env-test/node_modules/react-dom/cjs/react-dom-server.edge.production.js:4866:16)
      at renderNodeDestructive (/home/jinwatanabe/workspace/tmp/env-test/node_modules/react-dom/cjs/react-dom-server.edge.production.js:4684:7) {
    code: 'ERR_INVALID_URL',
    input: '/api/hello'
  }
}
Error occurred prerendering page "/add". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: Failed to parse URL from /api/hello
    at Object.fetch (node:internal/deps/undici/undici:13220:11)
    at async p (/home/jinwatanabe/workspace/tmp/env-test/.next/server/pages/add.js:1:740)
Export encountered an error on /add, exiting the build.
 ⨯ Static worker exited with code: 1 and signal: null
 ```

 おなじみのエラーなので、ホスト周りをみたり、環境変数周りをみても解決ができずでした

 # 解決方法

 このAPIを呼び出すために利用していたファイルの位置が悪さをしていました

 ```
┣ app
  ┣ page.tsx
┣ pages
  ┣ add.ts
  ┣ api
    ┣ hello.ts
```

```tsx:page.tsx
import AddMotivation from "../utils/add";

export default function Home2() {
  const handleAdd = async () => {
    await AddMotivation();
  }
  
  return (
    <div>
      <button onClick={handleAdd}>click</button>
    </div>
  )
}
```

```ts:add.ts
export default async function AddMotivation() {
  const res = await fetch(`/api/hello`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ title: "title", time: 1 }),
  });
  const data = await res.json();
  return data;
}
```

ページでは`add.ts`の関数を経由してAPIを読んでいましたがこのファイルの位置が`pages/add.ts`にありました。

Next.jsではディレクトリ構造に意味があるため、`npm run build`のときにAPIとして？ビルドしようとしてしまうのが問題だったかと思われます。

# おわりに

このパターンは初めてだったので環境変数やホストをかなり疑いました。
しっかりと切り分けをしていくのが大切なのを学びました