Debugging and Resolving Complex Issues in Next.js Applications

September 6, 2025 Next.js Debugging Hydration Error Internationalization Favicon

Debugging and Resolving Complex Issues in Next.js Applications

Introduction

This article details the process of identifying and resolving multiple technical issues that occurred in a Next.js application through interaction with the Gemini CLI. In particular, a deep understanding of Next.js's rendering mechanisms and internationalization was required. With the assistance of the Gemini CLI, we delved into each problem one by one and applied solutions.

Problem 1: Resolving Hydration Errors

Initial Symptoms

Upon initial loading of the application, especially when directly accessing the top page, the following Hydration error was displayed in the console:

Error: Hydration failed because the initial UI does not match what was rendered on the server.
Expected server HTML to contain a matching <div> in <a>.

This error exhibited strange behavior, disappearing after a page transition.

Cause and Trial and Error

This error occurs when the HTML rendered on the server-side does not match the HTML hydrated on the client-side. The specific message, indicating a <div> nested within an <a> tag, provided a clue.

  1. Nesting issue within Link component in JobCard.tsx:

    • Initially, it was thought that the Link component within src/components/JobCard.tsx was rendering an <a> tag and directly containing a <div> as its child element. In HTML semantics, block-level elements cannot be directly nested within an <a> tag.
    • We attempted a fix using the legacyBehavior property, explicitly passing an <a> tag as a child of Link and placing the <div> inside that <a> tag.
    • However, this fix caused a syntax error: Unexpected token Link, requiring manual correction. Ultimately, another problem emerged: an <a> tag nested within an <a> tag.
  2. Nested <a> tag within JobCard.tsx:

    • Within JobCard.tsx, an <a> tag displaying the job poster's email address as a link was nested within an <a> tag rendered by the outer Link component.
    • This was resolved by changing it to a <span> tag, eliminating the nested <a> tag issue.
  3. Use of key={Date.now()}:

    • src/app/[locale]/page.tsx had key={Date.now()} set for the JobListingClient component. Date.now() generates different values on the server and client, which can cause Hydration errors.
    • This key property was removed.
  4. dangerouslySetInnerHTML in Analytics.tsx:

    • The Google Analytics tracking code within src/components/Analytics.tsx used dangerouslySetInnerHTML to directly embed window.location.pathname. Since the window object does not exist on the server-side, the HTML generated on the server and client differed, causing Hydration errors.
    • This was fixed by using the usePathname() hook to get the path and embedding it within dangerouslySetInnerHTML.
  5. Duplicate i18n initialization logic in Header.tsx:

    • src/components/Header.tsx was re-initializing the i18n instance with createInstance(). This was a duplication of the process already performed in layout.tsx and could potentially cause Hydration errors.
    • The i18n initialization logic was removed from Header.tsx, and useTranslation hook was used instead.
  6. Double import of useTranslation in Header.tsx:

    • During the above fix, an error occurred where useTranslation was imported twice. This was a simple import duplication and was corrected.
  7. Use of I18nProvider in layout.tsx:

    • src/app/[locale]/layout.tsx was not using react-i18next's I18nProvider. When using useTranslation in client components, I18nProvider must be present higher up in the component tree.
    • This was fixed by using I18nProvider in layout.tsx.

Final Resolution

As a result of applying the above multiple fixes, Hydration errors in the development environment were resolved. However, warnings such as Warning: Extra attributes from the server: data-new-gr-c-s-check-loaded,data-gr-ext-installed may remain, but these are usually due to browser extensions and do not affect the application's functionality.

Problem 2: Resolving Favicon 404 Issue

Initial Symptoms

When accessing the application, a GET /favicon.ico 404 error was displayed in the console, and the favicon was not displayed correctly.

Cause and Solution

In Next.js App Router, placing src/app/icon.png automatically recognizes it as a favicon, but browsers may still request favicon.ico. Also, the absence of favicon.ico in the public directory was the cause.

  1. Deletion of src/app/icon.png: To avoid conflicts with the favicon setting in the app directory, src/app/icon.png was deleted.
  2. Placement of public/favicon.ico: konnichiwork_favicon.png which was in the project root, was moved to the public directory and converted to favicon.ico format and placed there (this conversion and placement was a manual operation by the user).
  3. Deletion of favicon link from layout.tsx: Since public/favicon.ico is automatically recognized, the favicon link explicitly added to src/app/[locale]/layout.tsx was deleted.

With these fixes, the favicon is now displayed correctly.

Problem 3: Internationalization of Image Upload Button on Post Job Page

Initial Symptoms

The text of the image upload button on the Post job page (e.g., "No file chosen") was displayed only in Japanese and was not internationalized.

Cause and Solution

The default display of input type="file" depends on the browser, so it cannot be directly internationalized.

  1. Deletion of "No file chosen" display: The previously added message displayed when no file was selected was removed.
  2. Implementation of custom file input field:
    • The original input type="file" was hidden, and a custom UI combining label and span elements was implemented.
    • The label was set to display t('form_select_file', 'Select file'), and the span was set to display t('form_no_file_chosen', 'No file chosen') or t('form_file_uploaded', 'File uploaded').
  3. Addition of translation keys: New translation keys form_select_file, form_no_file_chosen, form_file_uploaded were added to public/locales/{lang}/common.json for each language (this was a manual operation by the user).

This improved the display by internationalizing the text of the image upload button.

Problem 4: Posted Job Not Translated Issue

Initial Symptoms

On the job details page, posted job information was displayed without being translated into the language selected by the user.

Cause and Solution

This issue is related to the translation logic using the Google Cloud Translation API.

  1. Addition of debug logs: Debug logs were added to src/app/api/translate/route.ts to check the API key settings, success/failure of API calls, and response content.
  2. Verification of environment variables and API: It was necessary to confirm whether GOOGLE_TRANSLATE_API_KEY was correctly set, whether the API key was valid, whether the Translation API was enabled in Google Cloud Platform, and whether there were any network connection issues.

Current Status: The addition of debug logs has been completed, but this issue has not been fully resolved yet. User confirmation of GOOGLE_TRANSLATE_API_KEY settings and server console logs is required. Based on this information, further debugging and application of solutions will be necessary.

Conclusion

Through collaboration with the Gemini CLI, we were able to identify and resolve a wide range of complex issues in the Next.js application, including Hydration errors, internationalization, favicons, and job translation. Debugging Hydration errors was particularly challenging, but by deeply understanding the role of each component and Next.js's rendering lifecycle, we were able to pinpoint the root cause. Although some issues required manual user intervention, the collaboration with the CLI enabled an efficient debugging and correction process.

← Previous Entry: Konnichiwork Site Improvement Report: From Translation Function Fixes to Account Deletion ImplementationNext Entry: International Student Recruitment Site Development in Japan
← Back to Blog List