{"record":{"id":"910b24e64135d818","repo":"ruvnet/ruflo","slug":"router-tools-fallback-failed-due-to-payment-requ","errorCode":null,"errorMessage":"[router] tools fallback failed due to payment required","messagePattern":"\\[router\\] tools fallback failed due to payment required","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ruflo/src/ruvocal/src/lib/server/router/endpoint.ts","lineNumber":250,"sourceCode":"\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tlogger.info(\n\t\t\t\t\t\t{ route: ROUTER_TOOLS_ROUTE, model: toolsCandidate },\n\t\t\t\t\t\t\"[router] tools active; bypassing Arch selection\"\n\t\t\t\t\t);\n\t\t\t\t\tconst ep = await createCandidateEndpoint(toolsCandidate);\n\t\t\t\t\tconst gen = await ep({ ...params });\n\t\t\t\t\treturn metadataThenStream(gen, toolsCandidate, ROUTER_TOOLS_ROUTE);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconst { message, statusCode } = extractUpstreamError(e);\n\t\t\t\t\tconst logData = {\n\t\t\t\t\t\troute: ROUTER_TOOLS_ROUTE,\n\t\t\t\t\t\tmodel: toolsCandidate,\n\t\t\t\t\t\terr: message,\n\t\t\t\t\t\t...(statusCode && { status: statusCode }),\n\t\t\t\t\t};\n\t\t\t\t\tif (statusCode === 402) {\n\t\t\t\t\t\tlogger.warn(logData, \"[router] tools fallback failed due to payment required\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.error(logData, \"[router] tools fallback failed\");\n\t\t\t\t\t}\n\t\t\t\t\tthrow statusCode ? new HTTPError(message, statusCode) : new Error(message);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst routeSelection = await archSelectRoute(sanitizedMessages, undefined, params.locals);\n\n\t\t// If arch router failed with an error, only hard-fail for policy errors (402/401/403)\n\t\t// For transient errors (5xx, timeouts, network), allow fallback to continue\n\t\tif (routeSelection.routeName === ROUTER_FAILURE && routeSelection.error) {\n\t\t\tconst { message, statusCode } = routeSelection.error;\n\n\t\t\tif (isPolicyError(statusCode)) {\n\t\t\t\t// Policy errors should be surfaced to the user immediately (e.g., subscription required)\n\t\t\t\tlogger.error(","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/ruflo/src/ruvocal/src/lib/server/router/endpoint.ts#L232-L268","documentation":"Log warning in makeRouterEndpoint: the tools-route bypass attempt failed with a payment-required class error (402), so the request is not retried on the tools model and routing proceeds to the fallback chain.","triggerScenarios":"Thrown at ruflo/src/ruvocal/src/lib/server/router/endpoint.ts:250 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Top up or fix billing for the fallback provider; HTTP 402 means the account cannot pay for the request."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}