Resolving NextJS Metadata Errors
- front
- blog
1. Introduction
This blog is currently undergoing migration to the app router of Next.js 13. A detailed discussion of this process will be posted later. Here, I summarize a minor issue that arose during the migration and consumed considerable time.
The page structure configured with the app router is organized as follows:
app
βββ (doc)
β βββ about
β β βββ page.tsx
β βββ posts
β β βββ [slug]
β β β βββ page.tsx
β βββ layout.tsx
βββ (page)
β βββ posts
β β βββ all
β β β βββ page.tsx
β β β βββ [page]
β β β β βββ page.tsx
β β βββ tag/[tag]
β β β βββ page.tsx
β β β βββ [page]
β β β β βββ page.tsx
β β βββ page.tsx
βββ main page
The /posts
page requires client state management due to its search functionality, thus it has been managed as a client component. Consequently, APIs like generateMetadata
, which are only usable in server components, were not utilized.
Unexpectedly, an error occurred on the /posts/tag/[tag]/[page]
page, which is constructed as a server component.
You are attempting to export "generateMetadata" from a component marked with "use client", which is disallowed. Either remove the export, or the "use client" directive. Read more: https://nextjs.org/docs/getting-started/react-essentials#the-use-client-directive
I made several attempts to resolve this issue, which I outline below.
2. Attempts to Resolve the Issue
2.1. Separate Client Components
The generateMetadata
API can only be used on the server side. Based on the error message, I speculated that the rendering of the /posts
page in use client
mode might be influencing the situation, so I attempted to change that first. The current structure of /posts/page.tsx
is as follows:
To address this, I created a new component named SearchPageBody
to handle the client rendering requirements and separated it into a pageBody.tsx
file. This component will render in use client
mode, while /posts/page.tsx
was modified for server-side rendering.
However, the error still persisted.
2.2. Change Routes
Upon reviewing the error message again:
You are attempting to export "generateMetadata" from a component marked with "use client", which is disallowed. Either remove the export, or the "use client" directive. Read more: https://nextjs.org/docs/getting-started/react-essentials#the-use-client-directive
,-[/Users/kimsunghyun/Desktop/nextjs-blog/src/app/(page)/posts/tag/[tag]/[page]/page.tsx:86:1]
86 | return paths;
87 | }
88 |
89 | export async function generateMetadata({ params }: Props): Promise<Metadata> {
: ^^^^^^^^^^^^^^^^
... abbreviated generateMetadata content...
The file path indicated seems to provide information about where the problem arises, targeting /posts/tag/[tag]/[page]
. Next.js documentation states that metadata is generated by traversing from the root segment until reaching the current page's page.js
. Therefore, I hypothesized that the metadata generation for /posts/tag/[tag]/[page]
might be influenced by traversing the /posts
route, thus causing the error.
I attempted to relocate the rendering component of /posts
to a different directory. I renamed /posts/page.tsx
to /search
. Nevertheless, the error merely changed the file path to ./src/app/(page)/search/page.tsx
.
Notably, when accessing a dynamic route such as /posts/tag/study/2
, the bug did not occur, even though generateMetadata
is located in /posts/tag/[tag]/[page]/page.tsx
, indicating that the issue was confined to /posts
.
2.3. Import Issues
Through these experiments, I surmised that there might be a dependency from the /posts
path to the /posts/tag/[tag]/[page]
segment.
When the imports create a static dependency graph, the /posts
route references /posts/tag/[tag]/[page]
, which contains generateMetadata
, leading to the assumption that /posts
is utilizing generateMetadata
, thus resulting in the aforementioned error.
Indeed, examining the imports in /posts/page.tsx
revealed...
Thus, adjusting the aforementioned section resolves the problem. It turned out to be a trivial cause.
3. Follow-Up Actions
Since the ITEMS_PER_PAGE
variable is used in many places, defining it in each file is not ideal. Instead, it was placed in the src/utils/post.ts
file, where the functions for retrieving posts reside.
I then updated all import paths using this variable accordingly. For instance:
As a result, the generateMetadata-related error vanished. For similar reasons, the FIRST_PAGE
variable was also moved to src/utils/post.ts
, as it was originally placed in an odd location like src/app/(page)/posts/all/page.tsx
.
This seemingly trivial reason led to a bug that consumed nearly two days, reinforcing the importance of properly organizing even the smallest variables within the structure.
References
Next.js optimizing metadata documentation: https://nextjs.org/docs/app/building-your-application/optimizing/metadata