mastra-ai/mastra · error · Error

Invalid route path: "${path}". Path cannot contain '..', '?'

Error message

Invalid route path: "${path}". Path cannot contain '..', '?', or '#'

What it means

normalizeRoutePath validates route path strings used to build client URLs and throws when the path contains '..', '?', or '#'. These characters either enable path traversal or are reserved for query/fragment semantics, so the client rejects them up front instead of producing a malformed or unsafe URL.

Source

Thrown at client-sdks/client-js/src/utils/index.ts:18

import { RequestContext } from '@mastra/core/request-context';

/**
 * Normalizes a route path to ensure consistent formatting.
 * - Removes leading/trailing whitespace
 * - Validates no path traversal (..), query strings (?), or fragments (#)
 * - Collapses multiple consecutive slashes
 * - Removes trailing slashes
 * - Ensures leading slash (unless empty)
 *
 * @param path - The route path to normalize
 * @returns The normalized path (empty string for root paths)
 * @throws Error if path contains invalid characters
 */
export function normalizeRoutePath(path: string): string {
  let normalized = path.trim();
  if (normalized.includes('..') || normalized.includes('?') || normalized.includes('#')) {
    throw new Error(`Invalid route path: "${path}". Path cannot contain '..', '?', or '#'`);
  }
  normalized = normalized.replace(/\/+/g, '/');
  if (normalized === '/' || normalized === '') {
    return '';
  }
  if (normalized.endsWith('/')) {
    normalized = normalized.slice(0, -1);
  }
  if (!normalized.startsWith('/')) {
    normalized = `/${normalized}`;
  }
  return normalized;
}

/**
 * Checks if a value is a "complex" type that needs JSON serialization for query params.
 * Complex types: objects (excluding Date), arrays
 * Primitive types: string, number, boolean, null, undefined, Date

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Inspect the path value passed to the client and remove any '?query=...' or '#fragment' parts; pass query params via the client's options instead.
  2. Sanitize identifiers used in paths (strip or encode '..', '?', '#') before constructing routes.
  3. If traversal was intended, restructure the call to use the correct base path/resource rather than relative '..' segments.
  4. Decode once and re-encode properly: use encodeURIComponent on dynamic segments so reserved chars never reach raw path form.
  5. Check version-specific behavior: if a previously-working path now throws, a validation release tightened normalizeRoutePath.

Example fix

// before
client.getAgent(`/api/agents/${name}?version=2`);
// after
client.getAgent(`/api/agents/${encodeURIComponent(name)}`, { query: { version: 2 } });
Defensive patterns

Strategy: validation

Validate before calling

function isValidRoutePath(path: string): boolean {
  const p = path.trim();
  return !p.includes('..') && !p.includes('?') && !p.includes('#');
}
if (!isValidRoutePath(userPath)) throw new Error('Rejected route path: ' + userPath);

Try / catch

try {
  normalizeRoutePath(userPath);
} catch (e) {
  if (e.message.startsWith('Invalid route path')) {
    console.warn('Sanitizing path', userPath);
    userPath = encodeURIComponent(userPath);
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a path string containing '..' (traversal segments), '?' (query string), or '#' (fragment) to any client helper that routes through normalizeRoutePath — e.g. building resource URLs from user-supplied agent/workflow/thread names or path segments.

Common situations: Concatenating user input or identifiers that contain query strings into route paths, double-encoding URLs so '?' or '#' survive, or building paths like '/api/agents/' + name where name came from an untrusted source or an old config with '../../other' style overrides.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/4600de2598452cf6. Report an issue: GitHub.