expo/expo · error

Expo Router Error: Expected navigation state to begin with o

Error message

Expo Router Error: Expected navigation state to begin with one of [${getRootStackRouteNames().join(', ')}] routes

What it means

When pre-parsing an href into navigation state, `getParamsAndNodeFromHref` expects the root-level route name to be one of the root stack's route names (or the internal slot). Anything else means the href cannot be mapped onto the root navigator.

Source

Thrown at packages/expo-router/src/link/preview/HrefPreview.tsx:151

        alignItems: 'center',
        gap: 8,
        backgroundColor: 'white',
      }}>
      <Text style={{ fontWeight: '600', fontSize: 24 }}>Invalid preview</Text>
      <Text style={{ fontWeight: '200', fontSize: 14 }}>{pathname}</Text>
    </View>
  );
}

function getParamsAndNodeFromHref(
  hrefState: ResultState,
  rootRouteNode: RouteNode | null | undefined
) {
  const index = hrefState?.index ?? 0;
  if (hrefState?.routes[index] && hrefState.routes[index].name !== INTERNAL_SLOT_NAME) {
    const error = `Expo Router Error: Expected navigation state to begin with one of [${getRootStackRouteNames().join(', ')}] routes`;
    if (process.env.NODE_ENV !== 'production') {
      throw new Error(error);
    } else {
      console.warn(error);
    }
  }
  const initialState = hrefState?.routes[index]?.state;
  const { routeNode, params } = findRouteNodeAndParamsForState(rootRouteNode, initialState);

  // Linking has already parsed these values into the public search-param shape.
  return { params: params as UnknownOutputParams, routeNode, state: initialState };
}

const displayWarningForProp = (prop: string) => {
  if (process.env.NODE_ENV !== 'production') {
    console.warn(
      `navigation.${prop} should not be used in a previewed screen. To fix this issue, wrap navigation calls with 'if (!isPreview) { ... }'.`
    );
  }
};

View on GitHub (pinned to 7da61120be)

Solutions

  1. Check the href points to an existing route name at the root stack level
  2. Verify route groups `(group)` syntax — group names are not part of the URL
  3. Run `npx expo-router typed-routes` or inspect the route tree to confirm valid paths
  4. In dev the throw surfaces immediately; fix the href rather than suppressing the warning

Example fix

// before
<Link href="/(tabs)/unknown/sheet" />
// after
<Link href="/unknown" /> // route that exists at the root stack
Defensive patterns

Strategy: validation

Validate before calling

// validate href before passing to Link/router
const validRootNames = ['index', '(tabs)', '(app)']; // your root stack route names
if (!validRootNames.some(n => href.startsWith('/' + n.replace(/\(.*\)/, '')))) console.warn('href does not resolve to a root route:', href);

Type guard

function isResolvedHref(href: string): boolean { return !href.startsWith('//') && !href.includes('..'); }

Try / catch

try { parseHref(href); } catch (e) { if (String(e).includes('Expected navigation state')) console.warn('Unresolvable href:', href); }

Prevention

When it happens

Trigger: An href string (passed to `<Link>`/`router`/`HrefPreview`) resolves to a state whose first route name is not a root-stack route name and not INTERNAL_SLOT_NAME; dev throws, production warns.

Common situations: Typing an absolute href to a route that doesn't exist at the root (e.g. group/slot mismatch); using `../`-style or `+`-prefixed paths incorrectly; hrefs referencing routes removed after refactoring.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of expo/expo@7da61120be (2026-09-09). Data as JSON: /api/errors/e8cb612c004a4fe7. Report an issue: GitHub.