How to Fix: False positive in parallel slot layout type checking: TS71005: “props” is not a valid layout prop.
Fixing TS71005 in Next.js Parallel Slot Layouts: Why "props" is not a valid layout prop appears and how to resolve it
This bug is a false positive in Next.js layout type checking: a perfectly valid parallel route slot layout can fail with TS71005 and complain that "props" is not a valid layout prop. The issue usually appears when you define app/@parallel/layout.tsx and type the component in a way that is correct in React and TypeScript, but stricter than what Next.js currently recognizes for slot-based layouts.
Understanding the Root Cause
In the App Router, Next.js performs special type validation for framework files such as layout.tsx, page.tsx, and related route segment files. For a normal layout, Next.js expects props shaped like { children: React.ReactNode }. For a parallel slot layout, Next.js also allows named slot props such as { children, analytics, team } when folders like @analytics and @team exist.
The false positive happens because the framework-level type checker is not only checking the shape of the props object, but can also be sensitive to the parameter name and the exact way the props are declared. In affected versions, using a signature like function Layout(props: Props) inside a parallel slot layout can trigger an invalid diagnostic even though the object itself contains valid slot properties.
In other words, the issue is not that your React component is wrong. The issue is that Next.js route-aware type generation misidentifies the layout signature under a folder such as app/@parallel/layout.tsx and incorrectly flags props as unsupported.
This is why the error reads like a framework contract violation instead of a standard TypeScript error. TS71005 here is tied to Next.js-generated type constraints rather than ordinary TypeScript component typing.
Step-by-Step Solution
The most reliable workaround is to destructure the allowed layout props directly in the function parameter instead of accepting a single variable named props. This aligns better with what Next.js expects during its layout prop validation.
1. Identify the parallel slot layout file
Your file will typically look like one of these:
app/@parallel/layout.tsx
app/dashboard/@analytics/layout.tsx
app/settings/@team/layout.tsx
2. Replace a generic props parameter with direct destructuring
Problematic pattern:
type LayoutProps = {
children: React.ReactNode
parallel: React.ReactNode
}
export default function Layout(props: LayoutProps) {
return (
<>
{props.children}
{props.parallel}
</>
)
}
Recommended workaround:
type LayoutProps = {
children: React.ReactNode
parallel: React.ReactNode
}
export default function Layout({ children, parallel }: LayoutProps) {
return (
<>
{children}
{parallel}
</>
)
}
3. Make sure the prop name matches the slot folder name
If your slot folder is @parallel, the prop must be named parallel. If the folder is @analytics, the prop must be analytics.
app/
layout.tsx
@analytics/
layout.tsx
type LayoutProps = {
children: React.ReactNode
analytics: React.ReactNode
}
export default function Layout({ children, analytics }: LayoutProps) {
return (
<section>
{children}
<aside>{analytics}</aside>
</section>
)
}
4. Avoid adding unsupported extra props to layout components
Framework layout files only accept the props Next.js injects. For layouts, that usually means children and any valid parallel slot names. Do not add unrelated props such as title, user, or props wrappers expecting parent-passed values.
type InvalidLayoutProps = {
children: React.ReactNode
parallel: React.ReactNode
title: string
}
// This may fail because Next.js won't provide `title`
export default function Layout({ children, parallel, title }: InvalidLayoutProps) {
return (
<>
<h1>{title}</h1>
{children}
{parallel}
</>
)
}
5. Use a clean, framework-friendly signature
If you want the least error-prone version, keep the component signature explicit and simple:
export default function Layout({
children,
parallel,
}: {
children: React.ReactNode
parallel: React.ReactNode
}) {
return (
<>
{children}
{parallel}
</>
)
}
6. Upgrade Next.js if a fix is available
Because this is a framework type-checking bug, the long-term fix is often a Next.js version upgrade. Check the Next.js issue tracker and changelog for updates related to parallel routes, slot layout typing, or TS71005.
npm install next@latest react@latest react-dom@latest
Or with pnpm:
pnpm up next react react-dom
Working Examples
Example: single parallel slot
type LayoutProps = {
children: React.ReactNode
parallel: React.ReactNode
}
export default function Layout({ children, parallel }: LayoutProps) {
return (
<main>
<div>{children}</div>
<div>{parallel}</div>
</main>
)
}
Example: multiple parallel slots
type LayoutProps = {
children: React.ReactNode
analytics: React.ReactNode
team: React.ReactNode
}
export default function Layout({ children, analytics, team }: LayoutProps) {
return (
<div>
<section>{children}</section>
<aside>{analytics}</aside>
<aside>{team}</aside>
</div>
)
}
Example: root layout with no parallel slot
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
This last example is useful because it highlights the difference: a normal layout only receives children, while a parallel slot layout can also receive one or more named slot props.
Common Edge Cases
1. Slot prop name does not match the folder name
If your folder is @reports but your component expects analytics, the generated types and runtime expectations will not align.
app/@reports/layout.tsx
// Wrong
export default function Layout({ children, analytics }: {
children: React.ReactNode
analytics: React.ReactNode
}) {
return null
}
// Correct
export default function Layout({ children, reports }: {
children: React.ReactNode
reports: React.ReactNode
}) {
return null
}
2. Using React.FC for layout files
React.FC is not necessary here and can obscure the exact prop contract expected by Next.js. Prefer a plain exported function with explicit props.
type LayoutProps = {
children: React.ReactNode
parallel: React.ReactNode
}
export default function Layout({ children, parallel }: LayoutProps) {
return (
<>
{children}
{parallel}
</>
)
}
3. Adding route params to the wrong file
Layouts can receive params in some route contexts, but the file structure matters. If the error appears after introducing dynamic segments, verify that your layout sits under the correct route segment and that the rest of the prop signature still matches what Next.js expects.
4. Type errors persisting after code changes
Next.js may cache generated types. If you fixed the signature but still see the same diagnostic, clear build artifacts and restart the TypeScript server or dev process.
rm -rf .next
npm run dev
5. Importing a shared props type that includes extra keys
A shared type can accidentally include fields not injected by Next.js. Keep your layout prop types minimal and local when debugging framework type issues.
FAQ
Why does Next.js reject props if the object contains the right fields?
Because this issue comes from Next.js framework-specific type validation, not standard React typing. In affected cases, the validator incorrectly treats the layout signature as invalid when a generic props parameter is used in a parallel slot layout.
Is this a runtime bug or only a type-checking bug?
It is primarily a type-checking bug. Your component logic may be perfectly valid at runtime, but the build or editor fails because generated route types incorrectly flag the layout signature.
What is the safest pattern for parallel slot layouts?
Use a plain default-exported function and destructure children plus exact slot names directly in the parameter list. Keep the prop type narrow and aligned with the folder names.
In short, the practical fix for TS71005: "props" is not a valid layout prop is to stop passing a single props object in app/@slot/layout.tsx and instead define the component with direct destructuring of children and the named parallel slot props. If the issue persists, update Next.js and clear generated artifacts, because the root problem is a framework false positive rather than an actual mistake in your React code.