ruvnet/ruflo · error
Invalid route entry
Error message
Invalid route entry: ${JSON.stringify(r)} What it means
Thrown by loadPolicy() while validating each entry of the routes array. Every route must carry non-empty name, description, and primary_model; an entry missing any of these is echoed verbatim (JSON.stringify) in the message so the offending object is identifiable. This is a schema check on the router's routing table.
Solutions
- Find the exact object printed in the error message and add the missing field(s) with non-empty values.
- Cross-check field names against the Route type: name, description, primary_model (plus any optional fields).
- Validate the whole file before boot: jq 'map(select((.name // "" ) == "" or (.description // "") == "" or (.primary_model // "") == ""))' routes.json should print [].
- Ensure primary_model references an id that exists in the upstream model list, otherwise routing will fail later even after this check passes.
Example fix
// before
{ "name": "code", "primary_model": "qwen/qwen3-coder" }
// after
{ "name": "code", "description": "Coding and technical questions", "primary_model": "qwen/qwen3-coder" } Defensive patterns
Strategy: validation
Validate before calling
const required = ["name", "description", "primary_model"] as const;
for (const r of routes) {
for (const key of required) {
if (!r?.[key]) throw new Error(`route missing ${key}: ${JSON.stringify(r)}`);
}
} Type guard
function isRoute(r: unknown): r is { name: string; description: string; primary_model: string } {
const c = r as Record<string, unknown>;
return (
!!c &&
typeof c.name === "string" && c.name.length > 0 &&
typeof c.description === "string" && c.description.length > 0 &&
typeof c.primary_model === "string" && c.primary_model.length > 0
);
} Prevention
- Parse the routes file with zod to get all field errors in one message instead of first-failure throws.
- Add an editor JSON schema so invalid entries are caught while editing.
- Unit-test the policy loader against a known-good fixture.
When it happens
Trigger: A route object in the LLM_ROUTER_ROUTES_PATH file omits name, description, or primary_model, or sets them to empty strings/undefined (falsy). The loop fails on the first invalid entry.
Common situations: Hand-edited routes file where a field was deleted or left as a placeholder; export from a spreadsheet/LLM that dropped fields; renaming fields (e.g., model instead of primary_model) after reading older docs.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Routes config must be a flat array of routes
- Duplicate route name
- Router multimodal is enabled but…
- agent must be an object
- bench must be an object
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/5840e477aceb2df2.
Report an issue: GitHub.
Appendix: source
Thrown at ruflo/src/ruvocal/src/lib/server/router/policy.ts:18
import { readFile } from "node:fs/promises";
import { config } from "$lib/server/config";
import type { Route } from "./types";
let ROUTES: Route[] = [];
let loaded = false;
export async function loadPolicy(): Promise<Route[]> {
const path = config.LLM_ROUTER_ROUTES_PATH;
const text = await readFile(path, "utf8");
const arr = JSON.parse(text) as Route[];
if (!Array.isArray(arr)) {
throw new Error("Routes config must be a flat array of routes");
}
const seen = new Set<string>();
for (const r of arr) {
if (!r?.name || !r?.description || !r?.primary_model) {
throw new Error(`Invalid route entry: ${JSON.stringify(r)}`);
}
if (seen.has(r.name)) {
throw new Error(`Duplicate route name: ${r.name}`);
}
seen.add(r.name);
}
ROUTES = arr;
loaded = true;
return ROUTES;
}
export async function getRoutes(): Promise<Route[]> {
if (!loaded) await loadPolicy();
return ROUTES;
}
export function resolveRouteModels(
routeName: string,View on GitHub (pinned to fa13ee4ad6)