oxc-project/oxc · warning · OxcDiagnostic

Prevent usage of `next/script` in `next/head` component.

Error message

Prevent usage of `next/script` in `next/head` component.

What it means

Warning from oxlint rule `nextjs/no-script-component-in-head`. `next/script` manages its own injection and loading priority; nesting it inside `next/head`'s `<Head>` causes double handling and ordering bugs (classic symptom: the script never runs, or runs twice). The rule reports a `Script` from `next/script` placed anywhere in the subtree of a `Head` from `next/head`.

Source

Thrown at crates/oxc_linter/src/rules/nextjs/no_script_component_in_head.rs:12

use oxc_ast::{
    AstKind,
    ast::{ImportDeclarationSpecifier, JSXChild, JSXElementName},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};

use crate::{AstNode, context::LintContext, rule::Rule};

fn no_script_component_in_head_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Prevent usage of `next/script` in `next/head` component.")
        .with_help("See https://nextjs.org/docs/messages/no-script-component-in-head")
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct NoScriptComponentInHead;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Prevent usage of `next/script` in `next/head` component.
    ///
    /// ### Why is this bad?
    ///
    /// The `next/script` component should not be used in a `next/head` component.
    /// Instead move the `<Script />` component outside of `<Head>` instead.
    ///
    /// ### Examples

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Move the `<Script>` out of `<Head>`, directly into the page or component body.
  2. Rely on the default `afterInteractive` strategy so it loads after hydration without needing `Head` at all.

Example fix

// before
import Head from 'next/head';
import Script from 'next/script';
<Head>
  <Script id="x" src="/s.js" />
</Head>

// after
<Script id="x" src="/s.js" />
Defensive patterns

Strategy: validation

Validate before calling

// Script nested inside next/head's Head:
// rg -n -A4 '<Head' -g '*.tsx' src | rg '<Script'

Prevention

When it happens

Trigger: A `<Script>` element (imported from `next/script`) appearing as a descendant of a `<Head>` element imported from `next/head`, via the file's import specifiers.

Common situations: Assuming everything head-related belongs inside `<Head>`; migrating a raw `<script>` that sat in `<head>` by wrapping both in the new components at once.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/8521ac5b30d29a8f. Report an issue: GitHub.