A `UserProvider` with the user state, a `UserProfile` consumer rendered alongside (above) it. The consumer reads `useContext(UserContext)` and gets `null` forever — because it isn't a descendant of the Provider.
The vulnerable diff
// app/layout.tsx
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
{/* BUG: UserProfile renders OUTSIDE UserProvider */}
<UserProfile />
<UserProvider>{children}</UserProvider>
</body>
</html>
);
}What is wrong
`useContext(SomeContext)` walks up the React tree looking for the nearest matching `<SomeContext.Provider>`. If none is found, it returns the default value passed to `createContext(default)`. Consumers rendered above the Provider in the JSX never find it. The bug is silent if the default is `null` or an empty object — the consumer just sees 'logged out' user state and renders accordingly.
The attack
Symptom:
// In UserProfile:
const user = useContext(UserContext); // always null
// Renders "Please log in" even though user IS logged in elsewhere.Hard to spot because each component works in isolation; the bug is in the tree composition.
Mesrai's review comment
mesraipilot · Bot · reviewed 1 min ago
[mesrai] [code-review] [Language] [React-Context] [medium]
`<UserProfile />` is rendered as a sibling of `<UserProvider>`. The
consumer is not a descendant — `useContext` falls back to the
createContext default (likely null or empty).
Move the Provider higher in the tree so all consumers are descendants:
<UserProvider>
<UserProfile />
{children}
</UserProvider>
For top-of-tree providers, put them in app/layout.tsx so every page
beneath inherits.
Pro-tip: make `useUser()` throw when context is undefined — turns the
silent fallback into a visible error during development:
function useUser() {
const ctx = useContext(UserContext);
if (ctx === undefined) throw new Error("useUser outside UserProvider");
return ctx;
}The fix
// app/layout.tsx — fixed
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<UserProvider>
<UserProfile />
{children}
</UserProvider>
</body>
</html>
);
}Provider above consumer. Or specifically: the Provider must be a parent (any depth) of any component that calls `useContext`. Adding a runtime check in the consumer (`if (ctx === undefined) throw`) makes the misplacement loud during development instead of silent.
Why human review missed it
Context tree errors are hard to spot in code review because the components look right in isolation. The bug is at the composition level. Mesrai catches the shape by tracing the tree from each `useContext` call up to find its Provider — flags consumers without an ancestor Provider in the same render path.
Related rules + further reading
Mesrai rule pack: language/react-context-tree — flags consumers without an ancestor Provider.
React docs: passing data deeply with context.
Common in App Router refactors where the tree shape changes.
Takeaway
Provider above consumer in the tree. Throwing on undefined context turns silent misuse into loud errors. Mesrai catches the tree shape.