How to fix Dynamic route segment parameter must be a non-empty string in React
This error occurs in React Router when a dynamic route parameter receives an empty string or undefined value instead of a valid non-empty string. It typically happens when constructing navigation paths programmatically or when route parameters are not properly validated.
Quick fix
Fixes Dynamic route segment parameter must be a non-empty string
import { useNavigate } from 'react-router-dom';
function UserProfile({ userId }) {
const navigate = useNavigate();
const handleNavigate = () => {
// Validate parameter before navigation
if (!userId || userId.trim() === '') {
console.error('Invalid userId');
return;
}
navigate(`/users/${userId}`);
};
return <button onClick={handleNavigate}>View Profile</button>;
}- Validate parameters before navigation
- Add guards to Link components
- Use default values and optional parameters
- Validate data before rendering navigation
import { useNavigate } from 'react-router-dom';function UserProfile({ userId }) {const navigate = useNavigate();const handleNavigate = () => {// Validate parameter before navigationif (!userId || userId.trim() === '') {console.error('Invalid userId');return;}navigate(`/users/${userId}`);};return <button onClick={handleNavigate}>View Profile</button>;}Dynamic route segment parameter must be a non-empty string
What this error means
This error is thrown by React Router when you attempt to navigate to or define a route with a dynamic segment that contains an empty string. Dynamic route segments (parameters) in React Router must always be non-empty strings to ensure proper route matching and parameter extraction. React Router uses dynamic segments in route paths like `/users/:userId` where `:userId` is the parameter. When you navigate to such routes programmatically or render links, the parameter value must be a valid, non-empty string. Empty strings, `null`, or `undefined` values will trigger this error because they create invalid route paths that cannot be properly matched or parsed. This validation exists to maintain route integrity and prevent silent failures where a route might appear to work but actually match incorrectly or fail to extract parameters properly.
Typical symptoms
- Error thrown when using navigate() or Link components with dynamic routes
- Application crashes or shows error boundary when navigating between pages
- Routes fail to match even though the path structure looks correct
- useParams() returns empty object or undefined values unexpectedly
- TypeError or validation errors related to route parameter construction
Common causes
- Passing empty string, null, or undefined directly to dynamic route parameters in navigate() or Link href
- Constructing route paths using variables that can be empty or undefined without validation
- Using optional chaining or fallback values that resolve to empty strings in route generation
- Fetching ID or parameter from API/state that returns empty value before navigation
- Template literals or string concatenation creating paths with missing parameter values
- Destructuring props or params without default values when building navigation paths
- Using array or object methods (map, find) that can return undefined in route construction
How to fix "Dynamic route segment parameter must be a non-empty string"
Add validation to ensure route parameters are non-empty before using them in navigation:
import { useNavigate } from 'react-router-dom';
function UserProfile({ userId }) {
const navigate = useNavigate();
const handleNavigate = () => {
// Validate parameter before navigation
if (!userId || userId.trim() === '') {
console.error('Invalid userId');
return;
}
navigate(`/users/${userId}`);
};
return <button onClick={handleNavigate}>View Profile</button>;
}This prevents empty values from reaching the router.
Conditionally render Link components or disable them when parameters are invalid:
import { Link } from 'react-router-dom';
function UserCard({ user }) {
// Guard against missing or invalid IDs
if (!user?.id) {
return <span className="text-muted">User ID unavailable</span>;
}
return (
<Link to={{`/users/${user.id}`}}>
View Profile
</Link>
);
}You can also disable the link:
function UserCard({ user }) {
const userId = user?.id;
const isValidId = userId && userId.trim() !== '';
return isValidId ? (
<Link to={`/users/${userId}`}>View Profile</Link>
) : (
<span className="disabled-link">View Profile</span>
);
}Provide fallback values or make route segments optional when appropriate:
// Option 1: Default value
function ProductPage({ productId = 'featured' }) {
const navigate = useNavigate();
const handleNavigate = () => {
// productId will never be empty
navigate(`/products/${productId}`);
};
}
// Option 2: Optional route segment
// Define route with optional parameter
<Route path="/products/:id?" element={<ProductList />} />
// In component, handle missing parameter
function ProductList() {
const { id } = useParams();
if (!id) {
return <AllProducts />;
}
return <ProductDetail id={id} />;
}Ensure data is loaded and valid before rendering components with dynamic routes:
function UserDashboard() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchUsers().then(data => {
setUsers(data);
setLoading(false);
});
}, []);
if (loading) {
return <LoadingSpinner />;
}
return (
<div>
{users.map(user => {
// Filter out invalid entries
if (!user.id) {
console.warn('User missing ID:', user);
return null;
}
return (
<Link key={user.id} to={`/users/${user.id}`}>
{user.name}
</Link>
);
})}
</div>
);
}Use TypeScript to enforce non-empty strings at compile time:
import { useNavigate, useParams } from 'react-router-dom';
// Type guard for non-empty strings
type NonEmptyString = string & { __brand: 'NonEmptyString' };
function isNonEmptyString(value: unknown): value is NonEmptyString {
return typeof value === 'string' && value.trim().length > 0;
}
// Helper function for safe navigation
function useSafeNavigate() {
const navigate = useNavigate();
return (path: string, params: Record<string, unknown>) => {
const validatedParams: Record<string, string> = {};
for (const [key, value] of Object.entries(params)) {
if (!isNonEmptyString(value)) {
throw new Error(`Parameter '${key}' must be a non-empty string`);
}
validatedParams[key] = value;
}
// Build path with validated params
let finalPath = path;
for (const [key, value] of Object.entries(validatedParams)) {
finalPath = finalPath.replace(`:${key}`, value);
}
navigate(finalPath);
};
}
// Usage
function MyComponent({ userId }: { userId: string }) {
const safeNavigate = useSafeNavigate();
const handleClick = () => {
safeNavigate('/users/:userId', { userId });
};
}Advanced notes
React Router v6 vs v7: This error validation was strengthened in React Router v6 and later versions. Earlier versions (v5 and below) were more permissive but could lead to silent failures or incorrect route matching.
Optional Parameters: You can make route segments optional by adding ? to the parameter definition: /users/:userId?. This allows the parameter to be omitted entirely from the URL, but if provided, it must still be non-empty.
Splat Routes: For catch-all routes using *, React Router will parse the star parameter as an empty string if no segments match. Be prepared to handle empty strings when using splat routes: <Route path="/files/*" />
Type-Safe Routing: Consider using libraries like react-router-typesafe-routes or @tanstack/react-router for additional type safety and validation at compile time. These can catch parameter issues before runtime.
URL Building Helpers: Create centralized route generation functions that validate parameters:
const routes = {
user: (id: string) => {
if (!id?.trim()) throw new Error('User ID required');
return `/users/${id}`;
},
product: (id: string, tab?: string) => {
if (!id?.trim()) throw new Error('Product ID required');
return tab ? `/products/${id}/${tab}` : `/products/${id}`;
}
};
// Usage ensures validation
navigate(routes.user(userId));Testing: When testing components with dynamic routes, ensure your mock data includes valid IDs. Empty or missing IDs in test fixtures are a common source of this error in test environments.
Frequently asked questions
- What does "Dynamic route segment parameter must be a non-empty string" mean?
- This error is thrown by React Router when you attempt to navigate to or define a route with a dynamic segment that contains an empty string. Dynamic route segments (parameters) in React Router must always be non-empty strings to ensure proper route matching and parameter extraction. React Router uses dynamic segments in route paths like /users/:userId where :userId is the parameter.
- How do I fix "Dynamic route segment parameter must be a non-empty string"?
- This error occurs in React Router when a dynamic route parameter receives an empty string or undefined value instead of a valid non-empty string. It typically happens when constructing navigation paths programmatically or when route parameters are not properly validated.
- What causes "Dynamic route segment parameter must be a non-empty string"?
- Passing empty string, null, or undefined directly to dynamic route parameters in navigate() or Link href Constructing route paths using variables that can be empty or undefined without validation Using optional chaining or fallback values that resolve to empty strings in route generation
- Is the "Dynamic route segment parameter must be a non-empty string" error serious?
- It is a medium-severity error โ more of a blocker than a risk. The steps above resolve it.