vercel/next.js · error · napi::Error

GenericFailure

GenericFailure

Error message

invalid type for RouteHas: {type_}

What it means

At the JavaScript↔Rust NAPI boundary, Next.js passes route-condition objects (the `has` arrays from rewrites/redirects/headers) to Turbopack. NapiRouteHas::from_napi_value reads the 'type' property and matches it case-sensitively against "header", "query", "cookie", or "host". Any other value (e.g. "Header", "param", "method") returns a napi Error with Status::GenericFailure back to JavaScript.

Source

Thrown at crates/next-napi-bindings/src/turbopack.rs:182

        let type_ = object.get_named_property::<String>("type")?;
        Ok(match type_.as_str() {
            "header" => NapiRouteHas::Header {
                key: object.get_named_property("key")?,
                value: object.get_named_property("value")?,
            },
            "query" => NapiRouteHas::Query {
                key: object.get_named_property("key")?,
                value: object.get_named_property("value")?,
            },
            "cookie" => NapiRouteHas::Cookie {
                key: object.get_named_property("key")?,
                value: object.get_named_property("value")?,
            },
            "host" => NapiRouteHas::Host {
                value: object.get_named_property("value")?,
            },
            _ => {
                return Err(napi::Error::new(
                    Status::GenericFailure,
                    format!("invalid type for RouteHas: {type_}"),
                ));
            }
        })
    }
}

impl From<NapiRouteHas> for RouteHas {
    fn from(val: NapiRouteHas) -> Self {
        match val {
            NapiRouteHas::Header { key, value } => RouteHas::Header {
                key: key.into(),
                value: value.map(From::from),
            },
            NapiRouteHas::Query { key, value } => RouteHas::Query {
                key: key.into(),
                value: value.map(From::from),

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Use one of the exact lowercase types: "header", "query", "cookie", or "host".
  2. Double-check casing — the match is case-sensitive.
  3. Remove unsupported condition types; route on a supported dimension instead.

Example fix

// before
async redirects() {
  return [{ source: '/a', destination: '/b', has: [{ type: 'Header', key: 'x-foo' }], permanent: false }]
}

// after
async redirects() {
  return [{ source: '/a', destination: '/b', has: [{ type: 'header', key: 'x-foo' }], permanent: false }]
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate route `has` condition types before passing to Next.js config.
const VALID_TYPES = new Set(['header', 'query', 'cookie', 'host']);
function validateRouteHas(has) {
  for (const h of has) {
    if (!VALID_TYPES.has(h.type)) {
      throw new Error(`invalid route has type "${h.type}"; expected one of header|query|cookie|host`);
    }
  }
}

Type guard

// TypeScript narrowing for route `has` conditions.
type RouteHasType = 'header' | 'query' | 'cookie' | 'host';
function isRouteHasType(t: string): t is RouteHasType {
  return t === 'header' || t === 'query' || t === 'cookie' || t === 'host';
}

Prevention

When it happens

Trigger: Defining a route `has` condition in next.config.js (rewrites/redirects/headers) with a type value outside the supported set, or with wrong casing. The object crosses into the Turbopack NAPI binding and fails deserialization.

Common situations: Typing "Header" instead of "header"; attempting to use an unsupported condition type like "param" or "method" that webpack-era configs or tutorials may have suggested; copy-paste from docs that used different casing.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/2f85f0289d2fbecd. Report an issue: GitHub.