next.js: [NEXT-1089] Custom fonts in `ImageResponse` not working in App Dir

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.1.0: Sun Oct  9 20:14:30 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T8103
    Binaries:
      Node: 18.12.0
      npm: 8.19.2
      Yarn: 1.22.18
      pnpm: 7.25.1
    Relevant packages:
      next: 13.3.1-canary.1
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true), Data fetching (gS(S)P, getInitialProps), Metadata (metadata, generateMetadata, next/head, head.js)

Link to the code that reproduces this issue

https://stackblitz.com/edit/github-f6jt4y?file=app%2Fopengraph-image.js

To Reproduce

  1. Run the Server
  2. Check the error in console
  3. Alternatively open the generated path in new URL to get the error.

Describe the Bug

While importing custom fonts, it throws the following error.

error - unhandledRejection: Error [TypeError]: Failed to parse URL from /_next/static/media/Inter-Regular.f356e84a.woff
    at new Request (node:internal/deps/undici/undici:9474:19)
    at fetch1 (webpack-internal:///(sc_server)/./node_modules/.pnpm/next@13.3.1-canary.1_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/compiled/react/cjs/react.shared-subset.development.js:193:39)
    at doOriginalFetch (/Users/.../opengraph/node_modules/.pnpm/next@13.3.1-canary.1_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/server/lib/patch-fetch.js:159:24)
    at /Users/.../opengraph/node_modules/.pnpm/next@13.3.1-canary.1_biqbaboplfbrettd7655fr4n2y/node_modules/next/dist/server/lib/patch-fetch.js:253:20 {
  digest: undefined
}

Expected Behavior

It should not throw error. Instead it should load properly.

Which browser are you using? (if relevant)

Any

How are you deploying your application? (if relevant)

No response

NEXT-1089

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 15
  • Comments: 31 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Yeah, using the exact example in the doc in the latest/canary Next.js version will still fail with the above error. https://nextjs.org/docs/app/api-reference/file-conventions/metadata/opengraph-image#generate-images-using-code-js-ts-tsx

@huozhi Turns out it doesn’t work when there’s a dynamic data fetch. (I’ve updated my reproduction)

export default async function og() {
   const res = await fetch("https://jsonplaceholder.typicode.com/todos/1", {
     cache: "no-store",
   });

And this workaround no longer works as well.

Edit Interestingly, if I load the font with a function, then it works, i.e.

const getInterSemiBold = async () => {
 const response = await fetch(
    new URL('./Inter-SemiBold.ttf', import.meta.url)
  );
  const interSemiBold = await response.arrayBuffer();

  return interSemiBold;
}

// ...
new ImageResponse(
  <OgImage />,
  {
    fonts: [
      {
        name: 'Inter',
        data: await getInterSemiBold(),
        style: 'normal',
        weight: 400,
      },
    ],
  }
)

I can repro this on latest canary (13.3.1-canary.11) as well, will let the team know!

Yeah can repro that, we take a look.

I’m having the same issue; as a workaround, you can do this: Put your font in /public/fonts/here.tff

async function getFont(): Promise<Buffer> {
  const url = process.env.APP_URL
  return new Promise((resolve, reject) => {
    http.get(`${url}/fonts/Font.ttf`, (res) => {
      const chunks: any[] = []
      res.on('data', c => chunks.push(c))
      res.on('end', () =>
        resolve(Buffer.concat(chunks))
      )
    }).on('error', (err) => {
      reject(err)
    })
  })
}
fonts: [
{
  data: await getFont()
}
]

This is pretty hacky, it would be nice if we could use next/font w/ ImageResponse

Confirmed, got it working with:

  • edge function
  • function in global scope const getFont = async () => { const res = await fetch( new URL('@/fonts/Inter/static/Inter-SemiBold.ttf', import.meta.url) ); return await res.arrayBuffer(); };
  • not in public directory

@huozhi Turns out it doesn’t work when there’s a dynamic data fetch. (I’ve updated my reproduction)

export default async function og() {
   const res = await fetch("https://jsonplaceholder.typicode.com/todos/1", {
     cache: "no-store",
   });

@lukadev-0 Can you try the latest canary it resolves the deployment issue for me

Also had this same issue