Skip to content

generateStaticParams silently ignored in route handler or opengraph-image.tsx when using cacheComponents #88043

@lourd

Description

@lourd

Link to the code that reproduces this issue

https://github.com/lourd/descioli.com/tree/cache-components

To Reproduce

  1. Clone the application, install deps, run build
  2. See that the [slug[/opengraph-image routes are static
├ ● /[slug]/opengraph-image
│ ├ /grove/opengraph-image
│ ├ /mediated-matter/opengraph-image
│ ├ /out-here-archery/opengraph-image
│ └ [+4 more paths]
  1. Comment out either the date formatting, or font fetching. Run the build again.
  2. See that the [slug]/opengraph-image route is dynamic instead of static>
├ ƒ /[slug]/opengraph-image

Current vs. Expected behavior

I have a route handler for generating opengraph images for posts/pages on my blog. What I want to do is adopt cacheComponents and still statically generate the images. Despite using generateStaticParams, the opengraph image route is dynamic, whereas before adopting cacheComponents it was completely static. Before I was using a plain route handler with generateStaticParams. I switched to using the built-in opengraph-image feature, but the issue still remains, the route is dynamic instead of static.

Stepping through and figuring out what's making the route opengraph-image route dynamic:

  • Anything async other than awaiting the params. If I use async methods for reading files from the file system, those opt out of static rendering and make the route dynamic.
  • Any calls to fetch. I'm using fetch to download some font data. There's not really a way around this aside from downloading the fonts ahead of time and reading synchronously from the filesystem.
  • Any code that uses the Date constructor indirectly. I'm using date-fns to format the publication date:
format(story.data.publication, "LLLL do, yyyy", { in: utc })

This snippet alone changes the opengraph-image route from being statically generated to dynamic.

Note

As an aside, this type of date formatting also triggers an error when building static Pages with useCache. The build errors out that this must be in a client component in a Suspense boundary. This is confusing and unexpected when just trying to format a string that isn't relative to the current time.

These are all really opaque pitfalls. There's no warnings that get logged about the route being switched from static to dynamic or why.

What I would expect is for the route to stay static when explicitly using generateStaticParams.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0: Mon Oct 20 19:33:00 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T6020
  Available memory (MB): 32768
  Available CPU cores: 10
Binaries:
  Node: 24.10.0
  npm: 11.6.1
  Yarn: 1.22.19
  pnpm: 10.27.0
Relevant Packages:
  next: 16.1.1 // Latest available version is detected (16.1.1).
  eslint-config-next: N/A
  react: 19.2.3
  react-dom: 19.2.3
  typescript: 5.9.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

cacheComponents

Which stage(s) are affected? (Select all that apply)

next build (local)

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions