F1 · Writes the whole middleware and context surface under its pre-7.9.0 unstable_ spellings — unstable_createContext, unstable_RouterContextProvider, the unstable_middleware route key and unstable_getContext — none of which react-router has exported since 7.9.0
That react-router's middleware and context APIs are still behind the
unstable_prefix on the release a developer is on today. The belief is expressed five times across two tasks, in imports, in a route-config key, in a type annotation, in a data-router option and in a JSX prop, and it is never hedged on the prefix itself. Task 1(a) verbatim:import { unstable_createContext, redirect, type unstable_RouterContextProvider } from "react-router";, thenexport const userContext = unstable_createContext<User | null>();, then the route object{ path: "/dashboard", unstable_middleware: [authMiddleware], ... }. Task 2(a):unstable_getContext() { const context = new unstable_RouterContextProvider(); ... }as thecreateBrowserRouteroption. Task 2(b):<HydratedRouter unstable_getContext={...} />andnew unstable_RouterContextProvider()in the ExpressgetLoadContext. Task 1(b) restates it as a considered position rather than a slip: "unstable_createContext— creates a typed context token for the per-navigation store. This is part of the middleware feature, which is experimental (unstable_prefix) as of the version I have solid recall of. I'm not fully confident whether a later 7.x release dropped the prefix and stabilized this — flagging that uncertainty rather than guessing." THE HEDGE NAMES THE RIGHT POSSIBILITY AND THE CODE DOES NOT FOLLOW IT. Per HARNESS.md § The charge follows the designated form (JOURNAL/191), the charge reads the form the reply tells a reader to use, and this reply designates exactly one: every code block is prefixed, and the hedge offers no alternative spelling to ship. It is a single-form hedge, which that rule governs by the code-vs-claim rule and not as a hedged demonstration — there is no second form to read.
import {
unstable_createContext,
redirect,
type unstable_RouterContextProvider,
} from "react-router";
export const userContext = unstable_createContext<User | null>();
export const router = createBrowserRouter([
{
path: "/dashboard",
unstable_middleware: [authMiddleware],
Component: DashboardLayout,
children: [/* ... */],
},
]);
// 7.9.0 and above: `unstable_createContext` and `unstable_RouterContextProvider`
// are not exported — TS2305 and a bundler missing-export error. And the route's
// `unstable_middleware` key is a key the router no longer reads: it compiles,
// loads, runs, and the auth check never executes.import {
createContext,
redirect,
type RouterContextProvider,
} from "react-router";
export const userContext = createContext<User | null>();
export const router = createBrowserRouter([
{
path: "/dashboard",
middleware: [authMiddleware],
Component: DashboardLayout,
children: [/* ... */],
},
]);TWO FAILURE MODES IN ONE REPLY, and the severity is the worse of them. The named imports are breaks-build: unstable_createContext and unstable_RouterContextProvider are absent from 7.9.0's export list, so TypeScript reports TS2305 and a bundler reports a missing export — loud, immediate, cheap to fix.
The route-config key is the dangerous half and it is silently-wrong. A route object carrying unstable_middleware type-checks against an index signature, loads, and runs; the router reads middleware and finds nothing. The reply's own middleware is the auth guard — it fetches the user and throws redirect("/login") when there is none — so the observable result of shipping this is a /dashboard subtree that renders for signed-out visitors, with no error anywhere. The arm itself supplied the mechanism in Task 2(c), answering NO to whether the router flags an unrecognised route export and explaining that unknown exports are "silently ignored by the routing machinery".
- react-router CHANGELOG.md — 7.9.0, Minor Changes (read from the CHANGELOG.md shipped inside react-router@7.11.0) published 2025-09-12
Stabilize middleware and context APIs.
- Executed against the published packages (tools/audit/bisect-facts.mjs, 2026-09-23, JOURNAL/195; re-confirmed on three rungs this session) published 2026-09-23
unstable_middleware,unstable_createContext,unstable_RouterContextProvider,unstable_getContextandunstable_MiddlewareFunctionoccur in the shipped code of 7.3.0 through 7.8.2 and in none of 7.9.0 through 8.4.0;index.d.tsexportsunstable_createContextat 7.8.2 andcreateContextat 7.9.0.