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
- Use one of the exact lowercase types: "header", "query", "cookie", or "host".
- Double-check casing — the match is case-sensitive.
- 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
- Always lowercase the `type` field in route `has` conditions.
- Restrict the type to the four supported values using a TypeScript union.
- Add a unit test over your next.config rewrites/redirects/headers to catch typos.
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
- Invalid "${name}" provided, expected a finite number of seco
- Specified distDir is not a string, found type "${typeof valu
- --routes cannot be empty
- Each route must start with '/': ${route}
- @next/font/google failed to run or is incorrectly configured
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/2f85f0289d2fbecd.
Report an issue: GitHub.