Skip to content

transport: unify server-side turn error handling#60

Merged
JoaoDiasAbly merged 1 commit intomainfrom
fix/AIT-667
Apr 21, 2026
Merged

transport: unify server-side turn error handling#60
JoaoDiasAbly merged 1 commit intomainfrom
fix/AIT-667

Conversation

@JoaoDiasAbly
Copy link
Copy Markdown
Contributor

@JoaoDiasAbly JoaoDiasAbly commented Apr 17, 2026

Fix three inconsistencies in server transport error handling:

  • Make addMessages() and addEvents() call the per-turn onError on publish failure, matching start() and end().
  • Surface stream errors from streamResponse() via StreamResult.error (preserving the original type for provider-specific inspection) and via onError wrapped as Ably.ErrorInfo with the new StreamError code. streamResponse() still does not throw on stream errors.
  • Rewrite onError JSDoc to document all three delivery scenarios (thrown, returned in StreamResult, or sole notification for onCancel handler failures) and clarify that turn errors never render the transport unusable.

Broaden TurnLifecycleError (104003) to cover all turn publish failures. Add StreamError (104008) for source stream failures.

Tests cover the new onError paths for addMessages/addEvents/ streamResponse and the StreamResult.error contract on complete, cancel, and error paths.

AIT-667

@github-actions github-actions Bot temporarily deployed to staging/pull/60/typedoc April 17, 2026 11:08 Inactive
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 17, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 93.28% 2236 / 2397
🔵 Statements 91.6% 2390 / 2609
🔵 Functions 93.62% 411 / 439
🔵 Branches 78.79% 1033 / 1311
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/errors.ts 100% 100% 100% 100%
src/core/transport/pipe-stream.ts 100% 100% 100% 100%
src/core/transport/server-transport.ts 94.18% 70% 90.9% 94.54% 102-109, 191, 228-246
src/core/transport/types.ts 0% 0% 0% 0%
Generated in workflow #202 for commit d14a0d6 by the Vitest Coverage Report Action

@JoaoDiasAbly
Copy link
Copy Markdown
Contributor Author

I think we first need to land these:

and then update the submodules pointers so CI will fully pass for this PR

@JoaoDiasAbly JoaoDiasAbly requested a review from zknill April 17, 2026 14:59
Comment thread src/core/transport/server-transport.ts
Comment on lines +475 to +480
const errInfo = new Ably.ErrorInfo(
`unable to stream response for turn ${turnId}; ${result.error.message}`,
ErrorCode.StreamError,
500,
result.error instanceof Ably.ErrorInfo ? result.error : undefined,
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This re-wraps errors thrown from encoder.appendEvent in pipeStream (i.e. ably publishes) but the js doc describes the ErrorCode.StreamError as though it's only an error from the LLM provider.

  /**
   * The source event stream threw during piping (e.g. LLM provider rate
   * limit, model error, network failure).
   */

Comment on lines +370 to +378
const errInfo = new Ably.ErrorInfo(
`unable to publish messages for turn ${turnId}; ${error instanceof Error ? error.message : String(error)}`,
ErrorCode.TurnLifecycleError,
500,
error instanceof Ably.ErrorInfo ? error : undefined,
);
logger?.error('Turn.addMessages(); publish failed', { turnId });
turnOnError?.(errInfo);
throw errInfo;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should expose this error twice; once in the onError callback and once thrown from here. 🤔

Copy link
Copy Markdown
Contributor

@zknill zknill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remaining items are nits, so dropping a +1 and you can merge when fixed

@github-actions github-actions Bot temporarily deployed to staging/pull/60/typedoc April 21, 2026 16:23 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/60/typedoc April 21, 2026 16:44 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/60/typedoc April 21, 2026 17:00 Inactive
Resolve three inconsistencies in server-side turn error handling
flagged in AIT-667.

- addMessages() and addEvents() now wrap publish failures as an
  Ably.ErrorInfo with code TurnLifecycleError and reject, matching
  start() and end(). All four lifecycle methods are consistent.

- streamResponse() surfaces caught errors via StreamResult.error
  (preserving provider-specific type) and via the per-turn onError
  wrapped as an Ably.ErrorInfo with the new StreamError code.
  streamResponse() still does not throw.

- The four lifecycle methods reject only; they do NOT also invoke
  onError. Per .claude/rules/ERRORS.md, an awaited method must not
  expose the same error through both a rejected promise and a
  callback. onError is reserved for paths with no other delivery
  channel (stream errors, onCancel handler failures).

Add StreamError (104008) and broaden TurnLifecycleError (104003)
to cover message and event publishes. Bump the ably-common submodule
to include 104008. Tests cover publish failures for all four
lifecycle methods, streamResponse stream errors (StreamResult.error
+ onError), and pipe-stream's new error-field contract.

[AIT-667]

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants