This error occurs when attempting to use the usePathname() hook in a Next.js Server Component. The hook relies on browser-side routing state that is unavailable during server-side rendering, requiring either conversion to a Client Component or alternative server-compatible approaches.
This error indicates a fundamental architectural conflict in Next.js App Router applications. The `usePathname()` hook is designed to access the current URL pathname by reading from the browser's routing state, which only exists in the client-side JavaScript runtime. Next.js Server Components, which execute on the server during the initial render, do not have access to this browser context. The error typically appears with the full message: "You're importing a component that needs usePathname. It only works in a Client Component but none of its parents are marked with 'use client', so they're Server Components by default." This happens because Next.js 13+ uses Server Components as the default rendering strategy, and any component file without an explicit "use client" directive at the top will be treated as a Server Component. This design is intentional by the Next.js team to support layout state preservation across page navigations and enable server-side optimizations. However, it means pathname-dependent logic must be carefully placed in the appropriate component boundary.
The simplest and most common solution is to mark your component as a Client Component by adding the "use client" directive at the very top of the file:
'use client'
import { usePathname } from 'next/navigation'
export default function NavigationComponent() {
const pathname = usePathname()
return (
<nav>
<a href="/" className={pathname === '/' ? 'active' : ''}>
Home
</a>
<a href="/about" className={pathname === '/about' ? 'active' : ''}>
About
</a>
</nav>
)
}This directive must be placed before any imports. It tells Next.js to treat this component and its dependencies as client-side code, allowing access to browser APIs like routing state.
Best practice is to keep Server Components at the top level and use Client Components only where needed. Create a small wrapper component for pathname-dependent logic:
// app/components/ActiveLink.tsx
'use client'
import { usePathname } from 'next/navigation'
import Link from 'next/link'
export function ActiveLink({ href, children }: { href: string; children: React.ReactNode }) {
const pathname = usePathname()
const isActive = pathname === href
return (
<Link href={href} className={isActive ? 'text-blue-600' : 'text-gray-600'}>
{children}
</Link>
)
}Then use it in your Server Component layout:
// app/layout.tsx (Server Component)
import { ActiveLink } from './components/ActiveLink'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<nav>
<ActiveLink href="/">Home</ActiveLink>
<ActiveLink href="/about">About</ActiveLink>
</nav>
{children}
</body>
</html>
)
}This approach minimizes the client-side JavaScript bundle while maintaining server rendering benefits.
If you need pathname information in a Server Component (e.g., for server-side authorization or conditional data fetching), use the headers API with middleware:
First, create middleware to pass the pathname as a header:
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-pathname', request.nextUrl.pathname)
return NextResponse.next({
request: {
headers: requestHeaders,
},
})
}Then read it in your Server Component:
// app/page.tsx (Server Component)
import { headers } from 'next/headers'
export default function Page() {
const headersList = headers()
const pathname = headersList.get('x-pathname')
// Use pathname for server-side logic
console.log('Current path:', pathname)
return <div>Current path: {pathname}</div>
}Note: The headers() function must be called directly in the component body, not in helper functions.
Often you can avoid usePathname entirely by using Next.js built-in params and searchParams props:
// app/products/[category]/page.tsx
export default function CategoryPage({
params,
searchParams
}: {
params: { category: string }
searchParams: { sort?: string }
}) {
// Access route segments directly
const category = params.category
const sortOrder = searchParams.sort
return (
<div>
<h1>Category: {category}</h1>
<p>Sort: {sortOrder}</p>
</div>
)
}This works in both Server and Client Components and is more type-safe than parsing pathname strings.
The error often occurs when a Client Component is imported into a Server Component without proper boundaries. Check your import chain:
// ❌ WRONG: Server Component importing Client Component without "use client"
// app/layout.tsx
import Sidebar from './Sidebar' // Sidebar uses usePathname but isn't marked
export default function Layout({ children }) {
return (
<div>
<Sidebar />
{children}
</div>
)
}// ✅ CORRECT: Sidebar.tsx has "use client" at the top
// app/Sidebar.tsx
'use client'
import { usePathname } from 'next/navigation'
export default function Sidebar() {
const pathname = usePathname()
// ... component logic
}Use your browser's DevTools or build logs to trace which component in the chain is missing the directive.
When using usePathname in Client Components, the server-rendered HTML won't have pathname information. Prevent hydration errors by using stable initial renders:
'use client'
import { usePathname } from 'next/navigation'
import { useEffect, useState } from 'react'
export function NavigationHighlight() {
const pathname = usePathname()
const [mounted, setMounted] = useState(false)
useEffect(() => {
setMounted(true)
}, [])
// Render stable content during SSR
if (!mounted) {
return <nav className="skeleton-loader" />
}
// Client-side only: show active states
return (
<nav>
<a href="/" className={pathname === '/' ? 'active' : ''}>
Home
</a>
</nav>
)
}This ensures the server and client render the same initial HTML, preventing React hydration warnings.
Architecture Patterns: The separation between Server and Client Components is a fundamental shift in Next.js 13+. Best practice is to use the "client boundary" pattern: keep most of your component tree as Server Components, and only add "use client" to the smallest possible leaf components that need interactivity or browser APIs. This maximizes server rendering benefits while minimizing JavaScript bundle size.
Middleware Considerations: When using the middleware + headers approach, be aware that middleware runs on edge runtime and has limitations (no Node.js APIs, limited package support). For complex pathname-based logic, consider whether it truly needs to run server-side or if client-side handling is acceptable.
Performance Trade-offs: Converting to Client Components isn't "bad" - it's about choosing the right tool. Client Components still benefit from React Server Components when used together. A navigation component that needs usePathname is a perfect use case for Client Components since navigation is inherently interactive.
TypeScript Support: Ensure your tsconfig.json has proper Next.js type support to catch these errors during development. The Next.js TypeScript plugin will warn you about hooks used in wrong contexts.
Testing Implications: When writing tests for components using usePathname, you'll need to mock the Next.js navigation hooks. Use libraries like next-router-mock for Jest/Vitest tests to simulate routing state.
Upcoming Changes: Next.js may introduce server-compatible pathname access in future versions, but the current architecture intentionally separates client-side routing state from server-side rendering to optimize streaming and partial prerendering features.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite