diegosouzapw/OmniRoute · error

Reflection retries exhausted

Error message

Reflection retries exhausted (${reflectionCount}/${maxReflectionLoops}) — pipeline verdict still "fail", returning the original failed result

What it means

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.

Solutions

  1. Inspect stage outputs and judge critiques to see whether the task itself is infeasible or the judge is too strict.
  2. Increase maxReflectionLoops only if the task genuinely benefits from more iterations.
  3. Fix the underlying stage error (model errors, malformed responses) that keeps retries failing.
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at open-sse/services/autoCombo/pipelineRouter.ts:351 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of diegosouzapw/OmniRoute@a179ffed5b (2026-08-25). Data as JSON: /api/errors/ef28ec48ac719804. Report an issue: GitHub.

Appendix: source

Thrown at open-sse/services/autoCombo/pipelineRouter.ts:351

    );

    const retryConfig = buildPipelineConfig(promptText, taskType);
    const retryResult = await executePipeline(retryConfig, wrappedExecutor);

    // Adopt the retry only if it passed; otherwise keep scanning until the loop
    // budget is exhausted, then fall through with the original result.
    if (retryResult.reflectVerdict === "pass") {
      result = retryResult;
      break;
    }
  }

  // G6 (silent-stop fix): if the reflection loop burned its retry budget and the
  // verdict is still "fail", the fall-through below returns a FAILED result
  // indistinguishable from a first-attempt failure. Surface it loudly so the
  // caller (and operator logs) can tell "retries exhausted" apart.
  if (result.reflectVerdict === "fail" && reflectionCount > 0) {
    log.warn(
      "PIPELINE",
      `Reflection retries exhausted (${reflectionCount}/${maxReflectionLoops}) — pipeline verdict still "fail", returning the original failed result`
    );
  }

  // ── Return result ─────────────────────────────────────────────────────────
  // Check if the last stage has a streaming Response
  const lastStage = result.stages[result.stages.length - 1];

  // If result contains a Response (from streaming final stage), return it directly
  // This happens when the pipeline decides to stream the final output
  if (lastStage?.text === "" && result.text) {
    // Non-streaming result — return as PipelineResult
    return result;
  }

  log.info(
    "PIPELINE",

View on GitHub (pinned to a179ffed5b)