Skip to content

[BUG] next/og - Failed to pipe response #602

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
murbanowicz opened this issue Apr 24, 2025 · 8 comments
Closed

[BUG] next/og - Failed to pipe response #602

murbanowicz opened this issue Apr 24, 2025 · 8 comments
Labels
bug Something isn't working triage

Comments

@murbanowicz
Copy link

Describe the bug

Hey
me again... I hope this is last issue for a while...
OpenGraph images with next/og

my code is pretty straight-forward

import { getCountryCode } from '@project/i18n';
import { getTranslations } from 'next-intl/server';
import { Inter } from 'next/font/google';
import { ImageResponse } from 'next/og';

import { ogImageSchema } from '@/lib/validations/og';

const inter = Inter({
  subsets: ['latin'],
  weight: ['400', '700'],
});

const [interRegular, interBold] = await Promise.all([
  fetch(new URL('/fonts/Inter-Regular.ttf', process.env.NEXT_BASE_URL)).then(
    (res) => res.arrayBuffer(),
  ),
  fetch(new URL('/fonts/Inter-Bold.ttf', process.env.NEXT_BASE_URL)).then(
    (res) => res.arrayBuffer(),
  ),
]);

export async function GET(req: Request) {
  try {
    const url = new URL(req.url);
    const { title, type, locale, country } = ogImageSchema.parse(
      Object.fromEntries(url.searchParams),
    );

    const t = await getTranslations({ locale, namespace: 'Og' });

    const fontSize = title.length > 80 ? '55px' : '70px';
    const paint = '#fff';

    const countryCode = country ? getCountryCode(country) : null;
    const flagUrl = countryCode
      ? `https://flagcdn.com/${countryCode}.svg`
      : null;
    let flagImage;
    if (flagUrl) {
      console.log('Fetching flag image...');
      const flagRes = await fetch(flagUrl);
      flagImage = await flagRes.arrayBuffer();
      console.log('Flag image fetched.');
    }

    console.log('Image generated. Will respond now.');

    return new ImageResponse(
      (
        <div
          tw="flex relative flex-col p-12 w-full h-full items-start text-white"
          style={{
            color: paint,
            background: 'linear-gradient(90deg, #000 0%, #111 100%)',
          }}
        >
          <div tw="flex flex-col flex-1 py-2">
            <div
              tw="flex text-3xl font-bold tracking-tight"
              style={{ fontFamily: 'Inter Bold', fontWeight: 'normal' }}
            >
              Project
            </div>
            <div
              tw="flex text-xl uppercase font-bold tracking-tight"
              style={{ fontFamily: 'Inter', fontWeight: 'normal' }}
            >
              {t(type)}
            </div>
            <div
              tw="flex leading-[1.1] text-[80px] font-bold pt-6"
              style={{
                fontFamily: 'Inter Bold',
                fontWeight: 'bold',
                marginLeft: '-3px',
                fontSize,
              }}
            >
              {title}
            </div>
          </div>
          <div tw="flex items-center w-full justify-between">
            <div
              tw="flex text-xl"
              style={{ fontFamily: 'Inter', fontWeight: 'normal' }}
            >
              project.com
            </div>
            {flagImage && (
              <img
                src={flagUrl!}
                width={96}
                height={64}
                style={{
                  borderRadius: '4px',
                  boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
                }}
              />
            )}
          </div>
        </div>
      ),
      {
        width: 1200,
        height: 630,
        fonts: [
          {
            name: 'Inter',
            data: interRegular,
            weight: 400,
          },
          {
            name: 'Inter Bold',
            data: interBold,
            weight: 700,
          },
        ],
      },
    );
  } catch (error) {
    console.error('OG Image generation error:', error);
    return new Response(`Failed to generate image`, {
      status: 500,
    });
  }
}

Everything is fetched, I see the logs for image being generated but then I hit "Failed to pipe response"
As always - works locally and on Vercel...

Steps to reproduce

Look at code.

Expected behavior

Image being generated and returned

@opennextjs/cloudflare version

latest beta

Wrangler version

latest

next info output

latest

Additional context

No response

@murbanowicz murbanowicz added bug Something isn't working triage labels Apr 24, 2025
@conico974
Copy link
Collaborator

I cannot reproduce with preview locally, could you provide a minimum reproduction repo

@murbanowicz
Copy link
Author

have you included flag? hardcode coutnry code. I will try to provide repro

@murbanowicz
Copy link
Author

https://kinde-intl-repro.marek-0e9.workers.dev/api/og - pure GET, values are hardcoded. Locally returns, throws on worker.

https://github.com/murbanowicz/kinde-next-intl-cloudflare-repro - same repo as before, disabled middleware to simplify

@murbanowicz
Copy link
Author

logs from the run:

Image

@conico974
Copy link
Collaborator

@murbanowicz Tested your repro, i still can't reproduce, locally with preview or deployed.
It works just fine for me

@murbanowicz
Copy link
Author

murbanowicz commented Apr 25, 2025

How is this possible? As you can see by clicking the link - it is throwing

@conico974
Copy link
Collaborator

I know what's going on, you're fetching fonts from your own worker domain. This does not work once deployed.
If you want to fetch from your own worker, you'll need to create a service binding (or reuse the one defined during caching)
See https://opennext.js.org/cloudflare/caching#small-site-using-revalidation the WORKER_SELF_REFERENCE binding

I was fetching from your worker domain (which is why it worked for me)

@murbanowicz
Copy link
Author

Im so grateful for your effort! Indeed it was this. I simplified it even more by uploading fonts to our static assets bucket. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working triage
Projects
None yet
Development

No branches or pull requests

2 participants