Skip to content

fix(agents,failover): propagate sessionId/lane/provider attribution through FailoverError#73506

Merged
altaywtf merged 2 commits into
openclaw:mainfrom
wenxu007:fix/failover-error-provider-attribution
May 1, 2026
Merged

fix(agents,failover): propagate sessionId/lane/provider attribution through FailoverError#73506
altaywtf merged 2 commits into
openclaw:mainfrom
wenxu007:fix/failover-error-provider-attribution

Conversation

@wenxu007

Copy link
Copy Markdown
Contributor

Summary

Threads originating-request attribution (sessionId, lane) plus the existing provider, model, profileId through FailoverError, describeFailoverError, and coerceToFailoverError so structured error-log ingestion (e.g. gateway.err.logapi_health_log) can attribute exhausted-fallback wrapper errors back to the originating session and last-attempted provider.

Root cause

Per the issue, ~18% of recent gateway errors had no provider or session_id populated. The underlying per-profile errors carried that metadata, but the final FailoverError wrapper produced after all profiles/models were exhausted dropped it: the class only stored provider/model/profileId, describeFailoverError only re-exposed message/rawError/reason/status/code, and coerceToFailoverError accepted no session-level context. Downstream loggers therefore had nothing to log.

Change

src/agents/failover-error.ts:

  • FailoverError gains optional readonly sessionId?: string and readonly lane?: string, populated from new constructor params (additive, fully backward-compatible).
  • describeFailoverError(err) now also returns provider, model, profileId, sessionId, lane when the error is a FailoverError. For non-FailoverError inputs it surfaces the recovered signal.provider so the at-the-throw provider context is preserved.
  • coerceToFailoverError(err, context) accepts sessionId and lane in context and threads them into the constructed FailoverError. Provider falls back to signal.provider when no context provider is given.

No call-site changes are required to land — existing callers continue to work, and code that currently passes { provider, model, profileId } can incrementally start passing sessionId/lane from runner/lane context.

Tests

src/agents/failover-error.test.ts:

  • propagates sessionId/lane/provider attribution through FailoverError (#42713) — constructs a FailoverError with the new fields and asserts both the instance fields and describeFailoverError(err) round-trip.
  • coerceToFailoverError carries sessionId/lane from context (#42713) — asserts the context fields land on the resulting FailoverError.

Notes

  • Session-id prefix normalization (session: vs raw) was called out by the reporter as a secondary concern. Leaving that to a follow-up so this change stays a non-breaking type-additive propagation patch — once sessionId is plumbed through, normalization can happen at one well-defined boundary.

Closes #42713.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels Apr 28, 2026
@greptile-apps

greptile-apps Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR extends FailoverError, describeFailoverError, and coerceToFailoverError to carry sessionId and lane attribution alongside the existing provider/model/profileId fields, addressing dropped metadata in structured error logs (~18% of gateway errors had no provider or session_id). All changes are additive and fully backward-compatible; two targeted tests cover the new round-trip behaviour.

Confidence Score: 5/5

Safe to merge — additive, non-breaking changes with good test coverage and no logic regressions.

All changes are purely additive optional fields. The public API is extended without altering existing call-site contracts. Tests verify both the constructor round-trip and the coerceToFailoverError enrichment path. No existing behaviour is removed or altered.

No files require special attention.

Reviews (1): Last reviewed commit: "fix(agents,failover): propagate sessionI..." | Re-trigger Greptile

@clawsweeper

clawsweeper Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge.

What this changes:

The PR adds optional sessionId/lane attribution to FailoverError and FallbackSummaryError, threads it through selected failover logging and CLI/embedded/auto-reply/cron call paths, adds targeted tests, and adds a changelog entry.

Required change before merge:

The remaining blocker is a narrow, source-level propagation gap with clear files and validation paths, so an automated repair on this PR branch or a replacement branch is reasonable.

Security review:

Security review cleared: The diff changes TypeScript failover attribution plumbing, tests, and changelog text; it does not touch workflows, dependencies, lockfiles, install or release scripts, package publishing metadata, secrets handling, or downloaded artifacts.

Review findings:

  • [P2] Thread attribution through remaining fallback callers — CHANGELOG.md:76
Review details

Best possible solution:

Land this as a complete attribution fix only after every fallback boundary that can produce exhausted wrapper errors supplies the available session and lane context, with regression coverage for the direct agent-command and queued follow-up paths. Keep session-id normalization as a separate follow-up unless the maintainer chooses to include it deliberately.

Do we have a high-confidence way to reproduce the issue?

Yes. A high-confidence static reproduction path exists: exhaust model fallback through the direct agent-command path or queued follow-up runner, where session context exists but is not passed to runWithModelFallback, then inspect the final FallbackSummaryError or model_fallback_decision structured fields.

Is this the best way to solve the issue?

No. The helper and selected call-site changes are directionally right, but the PR is not yet the narrow complete fix while central callers still omit the metadata needed for session_id attribution.

Full review comments:

  • [P2] Thread attribution through remaining fallback callers — CHANGELOG.md:76
    The new changelog and closing claim say exhausted fallback wrapper logs can be attributed to the originating session, but the patch still leaves the direct agent-command path and queued follow-up runner calling runWithModelFallback without sessionId/lane. Those paths can still throw FallbackSummaryError and emit model_fallback_decision logs without the fields that the structured logger promotes to session_id, so the linked issue is not fully fixed. Please pass the available session/lane context through those callers or narrow the changelog and closing claim.
    Confidence: 0.88

Overall correctness: patch is incorrect
Overall confidence: 0.87

Acceptance criteria:

  • pnpm test src/agents/failover-error.test.ts src/agents/model-fallback.test.ts src/agents/model-fallback.probe.test.ts
  • pnpm test src/auto-reply/reply/followup-runner.test.ts
  • pnpm test src/agents/agent-command.live-model-switch.test.ts
  • pnpm exec oxfmt --check --threads=1 CHANGELOG.md src/agents/failover-error.ts src/agents/model-fallback.ts src/agents/model-fallback-observation.ts src/agents/agent-command.ts src/agents/command/attempt-execution.ts src/auto-reply/reply/followup-runner.ts

What I checked:

  • Current main lacks FailoverError origin fields: FailoverError, describeFailoverError, and coerceToFailoverError on main only carry reason/provider/model/profileId/status/code/rawError, not sessionId or lane. (src/agents/failover-error.ts:16, a379ac056261)
  • Structured logger needs a supplied session field: buildStructuredFileLogFields only emits session_id when the log source includes session_id, sessionId, or sessionKey, so fallback wrapper and decision logs need one of those fields supplied upstream. (src/logging/logger.ts:341, a379ac056261)
  • Direct agent command fallback still lacks attribution in the PR: Current main's direct agent-command path has sessionId/sessionKey and opts.lane in scope, but its runWithModelFallback call passes only cfg/provider/model/runId/agentDir and hooks; the PR patch does not update this file. (src/agents/agent-command.ts:947, a379ac056261)
  • Queued follow-up fallback still lacks attribution in the PR: createFollowupRunner has run.sessionId/sessionKey available but calls runWithModelFallback without sessionId/lane; the PR patch updates agent-runner-execution but not this queued follow-up runner path. (src/auto-reply/reply/followup-runner.ts:264, a379ac056261)
  • PR head and scope: GitHub API reports PR head 26fdb9a with 15 changed files; the patch includes failover helper fields, fallback summary/logging fields, selected call-site plumbing, tests, and a changelog claim that the wrapper logs can now be attributed. (26fdb9a864d5)

Likely related people:

  • steipete: Recent main-history commits touch model fallback, fallback observability, alias resolution before fallback, direct agent command behavior, and auto-reply execution paths that are central to this attribution flow. (role: recent maintainer and adjacent owner; confidence: high; commits: 90419df6633f, aec5efed8d43, ab95812d65a6; files: src/agents/model-fallback.ts, src/agents/agent-command.ts, src/auto-reply/reply/agent-runner-execution.ts)
  • altaywtf: Recent main history includes failover-error classification work, and the latest PR commit expands the branch from helper-only propagation into fallback call-site attribution. (role: recent failover helper maintainer; confidence: medium; commits: 9d3c56d236fb, 26fdb9a864d5; files: src/agents/failover-error.ts, src/agents/model-fallback.ts)

Remaining risk / open question:

  • No live gateway.err.log to api_health_log ingestion was run in this read-only review; the finding is based on source inspection of the structured logger and fallback call graph.

Codex review notes: model gpt-5.5, reasoning high; reviewed against a379ac056261.

wenxu007 and others added 2 commits May 1, 2026 10:26
…hrough FailoverError

Adds optional `sessionId` and `lane` fields to `FailoverError` and threads
them — together with the existing `provider`, `model`, `profileId` — through
`describeFailoverError` and `coerceToFailoverError` context, so structured
error log ingestion can attribute exhausted-fallback wrapper errors back
to the originating request instead of dropping the per-profile metadata
when the final wrapper is built.

Fixes openclaw#42713.
@altaywtf
altaywtf force-pushed the fix/failover-error-provider-attribution branch from 408e1e0 to 26fdb9a Compare May 1, 2026 07:27
@altaywtf
altaywtf merged commit 9df0ae6 into openclaw:main May 1, 2026
104 of 105 checks passed
@altaywtf

altaywtf commented May 1, 2026

Copy link
Copy Markdown
Member

Merged via squash.

Thanks @wenxu007!

lxe pushed a commit to lxe/openclaw that referenced this pull request May 6, 2026
…hrough FailoverError (openclaw#73506)

* fix(agents,failover): propagate sessionId/lane/provider attribution through FailoverError

Adds optional `sessionId` and `lane` fields to `FailoverError` and threads
them — together with the existing `provider`, `model`, `profileId` — through
`describeFailoverError` and `coerceToFailoverError` context, so structured
error log ingestion can attribute exhausted-fallback wrapper errors back
to the originating request instead of dropping the per-profile metadata
when the final wrapper is built.

Fixes openclaw#42713.

* fix: preserve failover error attribution

---------

Co-authored-by: Altay <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…hrough FailoverError (openclaw#73506)

* fix(agents,failover): propagate sessionId/lane/provider attribution through FailoverError

Adds optional `sessionId` and `lane` fields to `FailoverError` and threads
them — together with the existing `provider`, `model`, `profileId` — through
`describeFailoverError` and `coerceToFailoverError` context, so structured
error log ingestion can attribute exhausted-fallback wrapper errors back
to the originating request instead of dropping the per-profile metadata
when the final wrapper is built.

Fixes openclaw#42713.

* fix: preserve failover error attribution

---------

Co-authored-by: Altay <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…hrough FailoverError (openclaw#73506)

* fix(agents,failover): propagate sessionId/lane/provider attribution through FailoverError

Adds optional `sessionId` and `lane` fields to `FailoverError` and threads
them — together with the existing `provider`, `model`, `profileId` — through
`describeFailoverError` and `coerceToFailoverError` context, so structured
error log ingestion can attribute exhausted-fallback wrapper errors back
to the originating request instead of dropping the per-profile metadata
when the final wrapper is built.

Fixes openclaw#42713.

* fix: preserve failover error attribution

---------

Co-authored-by: Altay <[email protected]>
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
…hrough FailoverError (openclaw#73506)

* fix(agents,failover): propagate sessionId/lane/provider attribution through FailoverError

Adds optional `sessionId` and `lane` fields to `FailoverError` and threads
them — together with the existing `provider`, `model`, `profileId` — through
`describeFailoverError` and `coerceToFailoverError` context, so structured
error log ingestion can attribute exhausted-fallback wrapper errors back
to the originating request instead of dropping the per-profile metadata
when the final wrapper is built.

Fixes openclaw#42713.

* fix: preserve failover error attribution

---------

Co-authored-by: Altay <[email protected]>
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
…hrough FailoverError (openclaw#73506)

* fix(agents,failover): propagate sessionId/lane/provider attribution through FailoverError

Adds optional `sessionId` and `lane` fields to `FailoverError` and threads
them — together with the existing `provider`, `model`, `profileId` — through
`describeFailoverError` and `coerceToFailoverError` context, so structured
error log ingestion can attribute exhausted-fallback wrapper errors back
to the originating request instead of dropping the per-profile metadata
when the final wrapper is built.

Fixes openclaw#42713.

* fix: preserve failover error attribution

---------

Co-authored-by: Altay <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failover wrapper errors missing provider and session_id in error logging

2 participants