remix-run/react-router · error · Error

No value found for context

Error message

No value found for context

What it means

`RouterContextProvider.get(context)` throws when no value has been set for the requested `RouterContext` AND the context has no `defaultValue`. The provider stores values in a private map; on miss it falls back to `context.defaultValue`, and only throws if that is also undefined.

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 1fd704a7da)

Solutions

  1. Ensure an upstream middleware (or `getLoadContext`) calls `context.set(MyContext, value)` before any downstream code calls `get(MyContext)`.
  2. Create the `RouterContext` with a `defaultValue` so reads never throw.
  3. Confirm all readers reference the exact same `RouterContext` instance the writer used (module identity).

Example fix

// before
const Ctx = createRouterContext<string>(); // no default
// in a loader:
context.get(Ctx); // throws

// after (option A: default)
const Ctx = createRouterContext<string>('guest');
// after (option B: set upstream)
export const middleware = async ({ context }, next) => {
  context.set(Ctx, 'user-123');
  return next();
};
Defensive patterns

Strategy: validation

Validate before calling

function hasContextValue<T>(p: RouterContextProvider, c: RouterContext<T>): boolean {
  try { p.get(c); return true; } catch { return false; }
}
if (!hasContextValue(context, MyContext)) context.set(MyContext, defaultValue);

Type guard

function tryGetContext<T>(p: RouterContextProvider, c: RouterContext<T>): T | undefined {
  try { return p.get(c); } catch { return undefined; }
}

Try / catch

let value: T;
try {
  value = context.get(MyContext);
} catch {
  value = fallbackValue;
}

Prevention

When it happens

Trigger: Calling `context.get(SomeContext)` from a loader/action/middleware for a context that was never set by an upstream middleware or by the server's getLoadContext, and whose `RouterContext` was created without a default.

Common situations: Forgetting to declare/set a shared context in a root middleware before a child route reads it; rename or refactor that changes the context object identity so `get` no longer finds the set value; reading context before the provider has been populated in the request lifecycle.

Related errors


AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12). Data as JSON: /api/errors/88ac77066a3db095. Report an issue: GitHub.