remix-run/react-router · error
No value found for context
Error message
No value found for context
What it means
RouterContextProvider.get(context) (lib/router/utils.ts:250) throws when no value was ever set for that context and it was created without a defaultValue. The intended flow is: a middleware on a parent route calls context.set() early, and loaders/actions below it call context.get(); reading before any setter ran is treated as a wiring bug.
Solutions
- Give the context a default: createContext<User | null>(null) so get() returns it instead of throwing
- Ensure the middleware that sets the value is defined on a parent route of every route that reads it
- Set the value unconditionally in middleware (fallback value) before any branch that skips it
- Check route nesting: the reading route must be nested under the middleware route
Example fix
// before export const userContext = createContext<User>() // after export const userContext = createContext<User | null>(null)
Defensive patterns
Strategy: validation
Validate before calling
// Defensive read: provide defaults at creation so get() never throws
export const userContext = createContext<User | null>(null);
// and ensure a value is always set before readers run
export const userMiddleware = async ({ context, request }) => {
context.set(userContext, (await getUser(request)) ?? null);
}; Try / catch
let user: User | undefined;
try { user = context.get(userContext) } catch (e) { if (e instanceof Error && e.message === 'No value found for context') user = undefined; else throw e } Prevention
- Create contexts with a defaultValue (createContext<T | null>(null)) unless absence is a bug
- Define the setting middleware on a parent route above every reader
- Set values unconditionally in middleware, using fallbacks in skipped branches
- Document which routes are under each context-setting middleware
When it happens
Trigger: context.get(myContext) in a loader whose middleware never ran (middleware defined on a different branch or a child of the reading route); forgot the context.set() call in the middleware; middleware ordering puts the reader above the setter in the route tree; reading in getContext() before middleware ran.
Common situations: Adding context reads to new routes while the middleware only matches sibling branches; refactoring moves middleware to a different route; conditional set inside middleware skipped on some paths.
Related errors
- Cannot call `runClientMiddleware()` from within an…
- You cannot call `runClientMiddleware()` from a static…
- You may only call `next()` once per middleware
- Failed to clone server response
- Missing body in server response
AI-assisted analysis of remix-run/react-router@7aea711dd1 (2026-08-18).
Data as JSON: /api/errors/88ac77066a3db095.
Report an issue: GitHub.
Appendix: source
Thrown at packages/react-router/lib/router/utils.ts:250
/**
* Access a value from the context. If no value has been set for the context,
* it will return the context's `defaultValue` if provided, or throw an error
* if no `defaultValue` was set.
* @param context The context to get the value for
* @returns The value for the context, or the context's `defaultValue` if no
* value was set
*/
get<T>(context: RouterContext<T>): T {
if (this.#map.has(context)) {
return this.#map.get(context) as T;
}
if (context.defaultValue !== undefined) {
return context.defaultValue;
}
throw new Error("No value found for context");
}
/**
* Set a value for the context. If the context already has a value set, this
* will overwrite it.
*
* @param context The context to set the value for
* @param value The value to set for the context
* @returns {void}
*/
set<C extends RouterContext>(
context: C,
value: C extends RouterContext<infer T> ? T : never,
): void {
this.#map.set(context, value);
}
}
View on GitHub (pinned to 7aea711dd1)