{"record":{"id":"ef28ec48ac719804","repo":"diegosouzapw/OmniRoute","slug":"reflection-retries-exhausted-reflectioncount","errorCode":null,"errorMessage":"Reflection retries exhausted (${reflectionCount}/${maxReflectionLoops}) — pipeline verdict still \"fail\", returning the original failed result","messagePattern":"Reflection retries exhausted \\((.+?)/(.+?)\\) — pipeline verdict still \"fail\", returning the original failed result","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"open-sse/services/autoCombo/pipelineRouter.ts","lineNumber":351,"sourceCode":"    );\n\n    const retryConfig = buildPipelineConfig(promptText, taskType);\n    const retryResult = await executePipeline(retryConfig, wrappedExecutor);\n\n    // Adopt the retry only if it passed; otherwise keep scanning until the loop\n    // budget is exhausted, then fall through with the original result.\n    if (retryResult.reflectVerdict === \"pass\") {\n      result = retryResult;\n      break;\n    }\n  }\n\n  // G6 (silent-stop fix): if the reflection loop burned its retry budget and the\n  // verdict is still \"fail\", the fall-through below returns a FAILED result\n  // indistinguishable from a first-attempt failure. Surface it loudly so the\n  // caller (and operator logs) can tell \"retries exhausted\" apart.\n  if (result.reflectVerdict === \"fail\" && reflectionCount > 0) {\n    log.warn(\n      \"PIPELINE\",\n      `Reflection retries exhausted (${reflectionCount}/${maxReflectionLoops}) — pipeline verdict still \"fail\", returning the original failed result`\n    );\n  }\n\n  // ── Return result ─────────────────────────────────────────────────────────\n  // Check if the last stage has a streaming Response\n  const lastStage = result.stages[result.stages.length - 1];\n\n  // If result contains a Response (from streaming final stage), return it directly\n  // This happens when the pipeline decides to stream the final output\n  if (lastStage?.text === \"\" && result.text) {\n    // Non-streaming result — return as PipelineResult\n    return result;\n  }\n\n  log.info(\n    \"PIPELINE\",","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/diegosouzapw/OmniRoute/blob/a179ffed5bb2e0b883b9ae7214ce8717b2a94c4d/open-sse/services/autoCombo/pipelineRouter.ts#L333-L369","documentation":"Pipeline reflection-loop exhaustion notice (G6 silent-stop fix): the verify→reflect→retry loop ran to its maxReflectionLoops budget and the last verdict is still \"fail\". The router stops retrying and returns the original failed result, tagging it so callers can distinguish a burned-budget failure from a first-attempt failure. Causes are persistent stage failures, unfixable prompt/task, or an over-strict judge.","triggerScenarios":"Thrown at open-sse/services/autoCombo/pipelineRouter.ts:351 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Inspect stage outputs and judge critiques to see whether the task itself is infeasible or the judge is too strict.","Increase maxReflectionLoops only if the task genuinely benefits from more iterations.","Fix the underlying stage error (model errors, malformed responses) that keeps retries failing."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"a179ffed5bb2e0b883b9ae7214ce8717b2a94c4d","analyzedAt":"2026-08-25T18:35:09.898Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}