{"record":{"id":"5840e477aceb2df2","repo":"ruvnet/ruflo","slug":"invalid-route-entry-json-stringify-r","errorCode":null,"errorMessage":"Invalid route entry: ${JSON.stringify(r)}","messagePattern":"Invalid route entry: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ruflo/src/ruvocal/src/lib/server/router/policy.ts","lineNumber":18,"sourceCode":"import { readFile } from \"node:fs/promises\";\nimport { config } from \"$lib/server/config\";\nimport type { Route } from \"./types\";\n\nlet ROUTES: Route[] = [];\nlet loaded = false;\n\nexport async function loadPolicy(): Promise<Route[]> {\n\tconst path = config.LLM_ROUTER_ROUTES_PATH;\n\tconst text = await readFile(path, \"utf8\");\n\tconst arr = JSON.parse(text) as Route[];\n\tif (!Array.isArray(arr)) {\n\t\tthrow new Error(\"Routes config must be a flat array of routes\");\n\t}\n\tconst seen = new Set<string>();\n\tfor (const r of arr) {\n\t\tif (!r?.name || !r?.description || !r?.primary_model) {\n\t\t\tthrow new Error(`Invalid route entry: ${JSON.stringify(r)}`);\n\t\t}\n\t\tif (seen.has(r.name)) {\n\t\t\tthrow new Error(`Duplicate route name: ${r.name}`);\n\t\t}\n\t\tseen.add(r.name);\n\t}\n\tROUTES = arr;\n\tloaded = true;\n\treturn ROUTES;\n}\n\nexport async function getRoutes(): Promise<Route[]> {\n\tif (!loaded) await loadPolicy();\n\treturn ROUTES;\n}\n\nexport function resolveRouteModels(\n\trouteName: string,","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/ruflo/src/ruvocal/src/lib/server/router/policy.ts#L1-L36","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n{ \"name\": \"code\", \"primary_model\": \"qwen/qwen3-coder\" }\n\n// after\n{ \"name\": \"code\", \"description\": \"Coding and technical questions\", \"primary_model\": \"qwen/qwen3-coder\" }","handlingStrategy":"validation","validationCode":"const required = [\"name\", \"description\", \"primary_model\"] as const;\nfor (const r of routes) {\n\tfor (const key of required) {\n\t\tif (!r?.[key]) throw new Error(`route missing ${key}: ${JSON.stringify(r)}`);\n\t}\n}","typeGuard":"function isRoute(r: unknown): r is { name: string; description: string; primary_model: string } {\n\tconst c = r as Record<string, unknown>;\n\treturn (\n\t\t!!c &&\n\t\ttypeof c.name === \"string\" && c.name.length > 0 &&\n\t\ttypeof c.description === \"string\" && c.description.length > 0 &&\n\t\ttypeof c.primary_model === \"string\" && c.primary_model.length > 0\n\t);\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["router","json","validation","configuration"],"backgroundTag":"schema-validation-failed","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}