remix-run/remix · error · CliError
RMX_ROUTE_MAP_LOADER_INVALID_JSON
RMX_ROUTE_MAP_LOADER_INVALID_JSON
Error message
Route-map loader returned invalid JSON.
What it means
The route-map loader subprocess exited successfully but the JSON it printed to stdout could not be parsed by JSON.parse. The contract requires the loader to emit a JSON route tree on stdout; anything else (logs, partial output, empty stdout) triggers this error.
Source
Thrown at packages/cli/src/lib/route-map.ts:138
if (exitResult.signal != null) {
throw routeMapLoaderSignal(exitResult.signal)
}
if (exitResult.code !== 0) {
let message = stderr.trim()
if (message.length === 0) {
message = 'Route-map loader failed.'
}
throw routeMapLoaderFailed(message)
}
let parsed: unknown
try {
parsed = JSON.parse(stdout)
} catch {
throw routeMapLoaderInvalidJson()
}
return assertRawRouteTree(parsed)
}
function decorateRouteTree(
rawTree: RawRouteTreeNode[],
ownership: ControllerOwnership,
): RouteTreeNode[] {
let subtreesByRouteName = new Map(
ownership.subtrees.map((subtree) => [subtree.routeName, subtree]),
)
let directoriesByRouteName = new Map(
ownership.routeDirectories.map((directory) => [directory.routeName, directory]),
)
return decorateRouteTreeWithLookup(rawTree, subtreesByRouteName, directoriesByRouteName)
}View on GitHub (pinned to 9696913134)
Solutions
- Remove or redirect any console.log in modules loaded by routes.ts (write to stderr instead)
- Ensure no middleware/plugin writes to stdout during route-map loading
- Reinstall to align CLI and worker versions so the JSON protocol matches
Example fix
// before (app/routes.ts module scope)
console.log('routes loaded')
// after
console.error('routes loaded') Defensive patterns
Strategy: try-catch
Validate before calling
const looksLikeJson = (stdout: string): boolean =>
stdout.trimStart().startsWith('[') || stdout.trimStart().startsWith('{') Type guard
const isJsonRouteTree = (value: unknown): value is unknown[] => typeof value === 'object' && value !== null && 'length' in value
Try / catch
catch (error) {
if (error instanceof Error && error.code === 'RMX_ROUTE_MAP_LOADER_INVALID_JSON') {
// instruct user to remove stdout writes from routes modules
}
throw error
} Prevention
- Never console.log at module scope in route modules; use console.error
- Pin the CLI and worker versions together in your lockfile
When it happens
Trigger: App code (or a plugin/preset) writing to stdout during route-map loading, corrupting the JSON stream; a loader version mismatch emitting a different format; empty stdout after a silent failure.
Common situations: Console.log calls at module scope in routes.ts or imported config polluting stdout; patched/mismatched CLI versions where the worker protocol changed.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- RMX_ROUTE_MAP_LOADER_INVALID_JSON
- RMX_ROUTE_MAP_LOADER_SIGNAL
- RMX_ROUTE_MAP_LOADER_FAILED
- hmr must be provided
- hmr requires watch mode
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/fe57908cd4aeb7ef.
Report an issue: GitHub.