Skip to content
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

Misleading "next-head-count is missing" error for invalid head tags #20924

Open
aengl opened this issue Jan 9, 2021 · 7 comments
Open

Misleading "next-head-count is missing" error for invalid head tags #20924

aengl opened this issue Jan 9, 2021 · 7 comments
Labels
good first issue Easy to fix issues, good for newcomers Linting Related to `next lint` or ESLint with Next.js. Metadata Related to Next.js' Metadata API.
Milestone

Comments

@aengl
Copy link

aengl commented Jan 9, 2021

What version of Next.js are you using?

10.0.5

What version of Node.js are you using?

12.20.1

What browser are you using?

Chrome

What operating system are you using?

macOS

How are you deploying your application?

Vercel

Describe the Bug

When using an unsupported/invalid tag in next/head, the console shows an unhelpful next-head-count is missing error and the content of next/head ends up in the body tag.

Example:

<Head>
  {/* The following line causes an error */}
  <html lang="en" />
  <title>Demo Page</title>
</Head>

Expected Behavior

Next.js should warn about the offending tag and gracefully ignore it.

To Reproduce

https://github.com/aengl/next-head-count-missing

Check out the project, run it via yarn dev and check the console output on the index page to see the error. Check the inspector to verify that the title tag was written into the HTML body.

Remove line 6 in components/SEO.tsx and the error will disappear:

<html lang="en" />

More extensive discussion of this error can be found here: #19361

@aengl aengl added the bug Issue was opened via the bug report template. label Jan 9, 2021
@timneutkens timneutkens added kind: bug and removed bug Issue was opened via the bug report template. labels Jan 11, 2021
@timneutkens timneutkens added this to the backlog milestone Jan 11, 2021
@timneutkens timneutkens added the good first issue Easy to fix issues, good for newcomers label Jan 11, 2021
@Timer Timer modified the milestone: backlog Jan 11, 2021
@Timer Timer added this to the backlog milestone Jan 19, 2021
@JorgeSivil
Copy link

JorgeSivil commented Mar 30, 2021

Same happened to us in another component

const MetaData = ({ pageData }) => {
  /**
   * For some NextJS reason, if you move this to the return, errors occur in console. "next-head-count is missing"
   * @return {JSX.Element}
   */
  const XxxId = () => {
    return <meta name="xxxid" property="xxxid" content={pageData.xxx.id} />;
  };

  return (
    <>
      <NoIndexMetaData pageData={pageData} />
      <link
        rel="canonical"
        href={`${
          pageData.canonicalLink.indexOf('//') === 0 ? `https:${pageData.canonicalLink}` : pageData.canonicalLink
        }${pageData.page > 1 ? `?page=${pageData.page}` : ''}`}
      />
      <link rel="publisher" href="https://plus.google.com/xxxxxx" />
      <XxxId />
      <TwitterMetaData pageData={pageData} />
      <OpenGraphMetaData pageData={pageData} />
    </>
  );
};

This is used in the component from nextjs

@ghrqq
Copy link

ghrqq commented Apr 11, 2021

Next.js's head count error may be caused by either literally wrong head count or using a tag within the Head which is not allowed. (For the other discussions you have m
entioned nested elements also causes it)

title, meta or any other elements (e.g. script) need to be contained as direct children of the Head element, or wrapped into maximum one level of <React.Fragment> or arrays—otherwise the tags won't be correctly picked up on client-side navigations. more here

HTML tag is not allowed within the Head component because during the render, Next.js places the Head component directly within the html tag where it belongs. 2021-04-11 07 32 54 pm

As a result when you type a html element within the Head component it causes error and because of this error, Head component does not deliver the data while Next.js expects a Head data, it does not receive and you see a head count error.

You may try to create a custom document and place the lang attribute in there.

Here is the example of what happens to the rendered head element when you use an illegal element.

2021-04-11 07 38 01 pm
2021-04-11 07 38 58 pm

@jonrh
Copy link

jonrh commented Apr 15, 2021

Had this happen and it took quite a while to figure out. A clearer warning as proposed would have been great. I was migrating a project from Gatsby to Next.js. In that migration I switched from react-helmet to next/head. To improve accessibility <html lang="is"> was specified. In react-helmet it is valid but it is not supported in next/head. As a result I got the next-head-count error and all <head> tags appeared in <body> instead.

jonrh added a commit to jonrh/jonogmarteinn.is that referenced this issue Apr 15, 2021
While reviewing a SEO warning in Lighthouse I noticed that the <head> tags did not appear in the <head> but instead at the top in <body>. After some looking around it seems that specifying `<html lang="is">` in next/head <Head> is not supported. It was supported in react-helmet which was used previously. A mistake I was not careful enough to spot while migrating from react-helmet to next/head.

This also fixes a next-head-count warning on the console. After some further digging it seems this is a known issue[0] with a proposed fix[1].

Since the website will only ever be in Icelandic it is enough to specify a i18n locale setting. That will then set the correct <html> lang attribute.

See:
[0]: vercel/next.js#20924
[1]: vercel/next.js#21080
@migueloller
Copy link
Contributor

It happened to me as well but in our case it was due to a user-provided snippet that included a <div> element. The browser seems to move everything after the <div> to the body resulting in Next.js not being able to find <meta name="next-head-count"> when calling querySelector("meta[name=next-head-count]").

Here's the lines of code where it happens:

const headCountEl: HTMLMetaElement = headEl.querySelector(
'meta[name=next-head-count]'
) as HTMLMetaElement

It's worth noting that it's not Next.js that places the invalid HTML in the body, but it's instead the browser, Chrome in my case. The response from the server indeed has the <div> in the head. So the problem here is Next.js just not being able to find the <meta name="next-head-count"> tag.

Since the browser seems to move everything that's after the invalid tag a potential solution for this would be to move the <meta name="next-head-count"> tag to the beginning of next/head's output instead of at the end.

@timneutkens timneutkens added the Metadata Related to Next.js' Metadata API. label Nov 18, 2021
@timneutkens
Copy link
Member

This can now be an ESLint rule I believe

@timneutkens timneutkens added the Linting Related to `next lint` or ESLint with Next.js. label Dec 7, 2021
@housseindjirdeh housseindjirdeh removed their assignment Jul 18, 2022
@itsjavi
Copy link

itsjavi commented Sep 15, 2023

This is also triggered when you accidentally nested Head elements, one inside another.
It's a stupid mistake from dev side, but I spent quite of time trying to figure out what was going on, because the error message was not helpful enough.

@sandeepkumar03
Copy link

sandeepkumar03 commented Oct 3, 2024

Related issue #50944, I think an uncaught error is happening in production breaking the page, probably page should be allowed to render like hydration errors. Not sure the reason of hard dependency of need of next-head-count at framework level that framework throws runtime error breaking the complete page. Unfortunately control also doesn't goes to _error file to handle it gracefully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Easy to fix issues, good for newcomers Linting Related to `next lint` or ESLint with Next.js. Metadata Related to Next.js' Metadata API.
Projects
None yet