expo/expo · error · Error

Input should not end with `/`

Error message

Input should not end with `/`

What it means

Input validation in `encodeInput`: route inputs must not end with `/`. A trailing slash would append `.txt` to form a path like `foo/.txt` under `_flight/<platform>/`, which is invalid and would collide or be lost during static export.

Source

Thrown at packages/@expo/cli/src/start/server/metro/createServerComponentsMiddleware.ts:644

    if (error instanceof TypeError) {
      throw Error(`Invalid URL: ${fileURL}`, { cause: error });
    }
    throw error;
  }
};

const encodeInput = (input: string) => {
  if (input === '') {
    return 'index.txt';
  }
  if (input === 'index') {
    throw new Error('Input should not be `index`');
  }
  if (input.startsWith('/')) {
    throw new Error('Input should not start with `/`');
  }
  if (input.endsWith('/')) {
    throw new Error('Input should not end with `/`');
  }
  return input + '.txt';
};

function wrapBundle(str: string) {
  // Skip the metro runtime so debugging is a bit easier.
  // Replace the __r() call with an export statement.
  // Use gm to apply to the last require line. This is needed when the bundle has side-effects.
  return str.replace(/^(__r\(.*\);)$/gm, 'module.exports = $1');
}

View on GitHub (pinned to b09195aac2)

Solutions

  1. Update `expo-router` and `@expo/cli` to matching versions.
  2. Inspect generated routes/redirects for trailing slashes and strip them.
  3. Clear the export cache (`expo export -c`).
  4. Report with the route tree if it reproduces on a clean project.

Example fix

// before — input retains a trailing slash from the route matcher
const input = route.input; // e.g. 'about/'

// after — strip trailing slashes before encoding
const input = route.input.replace(/\/+$/, ''); // 'about'
Defensive patterns

Strategy: validation

Validate before calling

function normalizeRouteInput(input: string): string {
  return input.replace(/\/+$/, '');
}
// const safe = normalizeRouteInput(route.input);

Type guard

function isValidRouteInput(input: string): boolean {
  return !input.endsWith('/') && !input.startsWith('/') && input !== 'index';
}

Prevention

When it happens

Trigger: Thrown at createServerComponentsMiddleware.ts:643 when `exportRoutesAsync` passes a `buildConfig` entry `input` that ends with `/` to `encodeInput`. Reached during `expo export` with static RSC routes.

Common situations: An expo-router version that leaves a trailing slash on route inputs; a catch-all or nested route whose input normalization drops the last segment but keeps the separator; a redirect targeting a directory-style URL.

Related errors


AI-assisted analysis of expo/expo@b09195aac2 (2026-08-12). Data as JSON: /api/errors/587350bf1e711669. Report an issue: GitHub.