Skip to content

KTOR-9411 Darwin: FrameTooBigException instead of generic exception#5453

Merged
osipxd merged 1 commit into
mainfrom
osipxd/darwin-frame-too-big
May 12, 2026
Merged

KTOR-9411 Darwin: FrameTooBigException instead of generic exception#5453
osipxd merged 1 commit into
mainfrom
osipxd/darwin-frame-too-big

Conversation

@osipxd
Copy link
Copy Markdown
Member

@osipxd osipxd commented Mar 18, 2026

Subsystem
Client Darwin

Motivation
KTOR-9411 Darwin throws DarwinHttpRequestException instead of FrameTooBigException

Solution
Add one more converter for NSError

@osipxd osipxd self-assigned this Mar 18, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 18, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: be9aa773-7aa6-46e5-b765-fcac70160dfc

📥 Commits

Reviewing files that changed from the base of the PR and between 9e5674f and 231d7d9.

📒 Files selected for processing (5)
  • ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinWebsocketSession.kt
  • ktor-client/ktor-client-tests/common/test/io/ktor/client/tests/WebSocketTest.kt
  • ktor-shared/ktor-websockets/api/ktor-websockets.api
  • ktor-shared/ktor-websockets/api/ktor-websockets.klib.api
  • ktor-shared/ktor-websockets/common/src/io/ktor/websocket/FrameTooBigException.kt
🚧 Files skipped from review as they are similar to previous changes (5)
  • ktor-shared/ktor-websockets/api/ktor-websockets.klib.api
  • ktor-client/ktor-client-tests/common/test/io/ktor/client/tests/WebSocketTest.kt
  • ktor-shared/ktor-websockets/api/ktor-websockets.api
  • ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinWebsocketSession.kt
  • ktor-shared/ktor-websockets/common/src/io/ktor/websocket/FrameTooBigException.kt

📝 Walkthrough

Walkthrough

Map Darwin EMSGSIZE websocket errors to FrameTooBigException; extend FrameTooBigException to accept a cause and implement CopyableThrowable; update WebSocket test to expect FrameTooBigException for oversized frames.

Changes

WebSocket Frame Size Error Handling

Layer / File(s) Summary
Exception Definition
ktor-shared/ktor-websockets/common/src/io/ktor/websocket/FrameTooBigException.kt
Primary constructor changed to FrameTooBigException(frameSize: Long, cause: Throwable? = null), calls Exception(cause), implements CopyableThrowable, adds deprecated binary-compat constructor, updates message formatting and createCopy() to include cause.
Public API / Metadata
ktor-shared/ktor-websockets/api/ktor-websockets.api, .../ktor-websockets.klib.api
Public API entries updated to expose the new constructor overload FrameTooBigException(long, Throwable?) and synthetic Kotlin interop variants.
Darwin Error Mapping
ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinWebsocketSession.kt
Added imports and EMSGSIZE handling; introduced convertWebsocketError(error: NSError): Exception mapping EMSGSIZE → FrameTooBigException; replaced direct DarwinHttpRequestException construction in didComplete() and receiveMessage() with the converter while preserving 401/close-code logic.
Tests
ktor-client/ktor-client-tests/common/test/io/ktor/client/tests/WebSocketTest.kt
testMaxFrameSizeSupported expectation changed to FrameTooBigException; removed obsolete Darwin-specific comment.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • ktorio/ktor#5112: Modifies DarwinWebsocketSession error handling in receiveMessage/error paths — touches the same area.
  • ktorio/ktor#5274: Rewires Darwin session/channel wiring; touches same file/class.
  • ktorio/ktor#5452: Converges on FrameTooBigException propagation for oversized frames.

Suggested reviewers

  • bjhham
  • e5l
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly describes the main change: enabling Darwin to throw FrameTooBigException instead of a generic exception, which is the core objective of this PR.
Description check ✅ Passed The description includes all required template sections: Subsystem (Client Darwin), Motivation (KTOR-9411 issue link), and Solution (converter for NSError). All sections are filled with appropriate context.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch osipxd/darwin-frame-too-big

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@osipxd osipxd force-pushed the osipxd/darwin-frame-too-big branch from f40d84a to e4ecf01 Compare May 6, 2026 13:42
@osipxd osipxd changed the base branch from release/3.x to main May 6, 2026 13:43
@osipxd osipxd marked this pull request as ready for review May 6, 2026 13:43
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

override fun createCopy(): FrameTooBigException = FrameTooBigException(frameSize).also {
it.initCauseBridge(this)

P2 Badge Preserve wrapped cause in FrameTooBigException.createCopy

Now that FrameTooBigException accepts a cause (used by Darwin via FrameTooBigException(..., DarwinHttpRequestException(error))), createCopy() should carry that cause forward. The current implementation rebuilds with only frameSize and then sets the copied exception’s cause to the original exception object, so after coroutine stacktrace recovery the immediate cause is no longer the original DarwinHttpRequestException. This breaks cause-based handling and makes diagnostics noisier when the exception crosses coroutine boundaries.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ktor-shared/ktor-websockets/common/src/io/ktor/websocket/FrameTooBigException.kt (1)

11-25: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Document the new public cause parameter.

The constructor surface changed here, but the KDoc still only describes frameSize. Please add cause so the public API docs stay accurate.

As per coding guidelines, "Public API requires KDoc documentation including parameters, return values, and notable exceptions."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ktor-shared/ktor-websockets/common/src/io/ktor/websocket/FrameTooBigException.kt`
around lines 11 - 25, Update the KDoc for class FrameTooBigException to document
the new public constructor parameter "cause": add an "@param cause" entry
explaining that it's the optional underlying Throwable that caused this
exception (nullable), and mention its role in exception chaining for the primary
constructor of FrameTooBigException; ensure the existing "@param frameSize" text
remains and that the deprecated secondary constructor comment need not change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinWebsocketSession.kt`:
- Around line 261-264: The Darwin mapping in convertWebsocketError currently
supplies a bogus negative frameSize (-1) to FrameTooBigException; instead make
the “unknown size” explicit: modify the convertWebsocketError handling to
construct FrameTooBigException with an explicit unknown-size representation
(e.g., pass null/Optional/absent size or a named constant like
UNKNOWN_FRAME_SIZE) rather than -1, and preserve wrapping with
DarwinHttpRequestException(error); update the call site in convertWebsocketError
and any FrameTooBigException constructors/usage to accept and display the
explicit unknown size representation.

---

Outside diff comments:
In
`@ktor-shared/ktor-websockets/common/src/io/ktor/websocket/FrameTooBigException.kt`:
- Around line 11-25: Update the KDoc for class FrameTooBigException to document
the new public constructor parameter "cause": add an "@param cause" entry
explaining that it's the optional underlying Throwable that caused this
exception (nullable), and mention its role in exception chaining for the primary
constructor of FrameTooBigException; ensure the existing "@param frameSize" text
remains and that the deprecated secondary constructor comment need not change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4abe8fad-dc06-402a-b5b4-e2ab57d4a4af

📥 Commits

Reviewing files that changed from the base of the PR and between cdf5f68 and e4ecf01.

📒 Files selected for processing (3)
  • ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinWebsocketSession.kt
  • ktor-client/ktor-client-tests/common/test/io/ktor/client/tests/WebSocketTest.kt
  • ktor-shared/ktor-websockets/common/src/io/ktor/websocket/FrameTooBigException.kt

@osipxd osipxd force-pushed the osipxd/darwin-frame-too-big branch from e4ecf01 to e2b353e Compare May 6, 2026 14:26
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinWebsocketSession.kt (1)

122-139: ⚡ Quick win

Apply convertWebsocketError to send paths for consistent EMSGSIZE mapping.

sendMessage completion handlers (and the ping handler at Line 156) still wrap the raw NSError in DarwinHttpRequestException directly. If EMSGSIZE surfaces while sending an oversized text/binary frame, callers will get DarwinHttpRequestException instead of FrameTooBigException, which contradicts the stated PR objective for outbound oversized frames. Routing all NSError-to-Exception conversions through convertWebsocketError keeps the mapping uniform.

♻️ Proposed change
                         ) { error ->
                             if (error == null) {
                                 continuation.resume(Unit)
                             } else {
-                                continuation.resumeWithException(DarwinHttpRequestException(error))
+                                continuation.resumeWithException(convertWebsocketError(error))
                             }
                         }

Apply the same substitution at Line 138 (binary send) and Line 156 (ping/pong).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinWebsocketSession.kt`
around lines 122 - 139, The send paths and ping handler currently wrap NSError
directly into DarwinHttpRequestException, so update the completion handlers for
task.sendMessage (used in FrameType.TEXT and FrameType.BINARY branches) and the
ping handler to call convertWebsocketError(error) instead of constructing
DarwinHttpRequestException(error) so that EMSGIZE/oversize errors are mapped to
FrameTooBigException; locate the send calls via task.sendMessage(...) and the
ping callback in DarwinWebsocketSession and replace
continuation.resumeWithException(DarwinHttpRequestException(error)) with
continuation.resumeWithException(convertWebsocketError(error)) (or
resumeWithException(convertWebsocketError(error))) to ensure uniform
NSError→Exception conversion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinWebsocketSession.kt`:
- Around line 122-139: The send paths and ping handler currently wrap NSError
directly into DarwinHttpRequestException, so update the completion handlers for
task.sendMessage (used in FrameType.TEXT and FrameType.BINARY branches) and the
ping handler to call convertWebsocketError(error) instead of constructing
DarwinHttpRequestException(error) so that EMSGIZE/oversize errors are mapped to
FrameTooBigException; locate the send calls via task.sendMessage(...) and the
ping callback in DarwinWebsocketSession and replace
continuation.resumeWithException(DarwinHttpRequestException(error)) with
continuation.resumeWithException(convertWebsocketError(error)) (or
resumeWithException(convertWebsocketError(error))) to ensure uniform
NSError→Exception conversion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6f08e855-cce7-493c-b210-f5affa18d952

📥 Commits

Reviewing files that changed from the base of the PR and between e4ecf01 and e2b353e.

📒 Files selected for processing (3)
  • ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinWebsocketSession.kt
  • ktor-client/ktor-client-tests/common/test/io/ktor/client/tests/WebSocketTest.kt
  • ktor-shared/ktor-websockets/common/src/io/ktor/websocket/FrameTooBigException.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • ktor-client/ktor-client-tests/common/test/io/ktor/client/tests/WebSocketTest.kt

@osipxd osipxd force-pushed the osipxd/darwin-frame-too-big branch from e2b353e to 9e5674f Compare May 6, 2026 16:28
@osipxd osipxd marked this pull request as draft May 6, 2026 19:56
@osipxd osipxd force-pushed the osipxd/darwin-frame-too-big branch from 9e5674f to d637dd2 Compare May 8, 2026 12:36
@osipxd osipxd force-pushed the osipxd/darwin-frame-too-big branch from d637dd2 to 231d7d9 Compare May 11, 2026 16:29
@osipxd osipxd marked this pull request as ready for review May 11, 2026 16:30
@osipxd osipxd requested a review from bjhham May 11, 2026 16:30
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 231d7d9eab

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +23 to +24
@Deprecated("Maintained for binary compatibility", level = DeprecationLevel.HIDDEN)
public constructor(frameSize: Long) : this(frameSize, cause = null)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve public one-arg constructor for Java callers

Marking the FrameTooBigException(Long) constructor as DeprecationLevel.HIDDEN makes that overload synthetic on JVM (as reflected in the updated ktor-websockets.api), so Java source code that previously compiled with new FrameTooBigException(size) will fail after this change unless it is rewritten to pass a second Throwable argument. This is a source-compatibility regression introduced by this commit and is likely unexpected for users upgrading within the same major line.

Useful? React with 👍 / 👎.

@osipxd osipxd enabled auto-merge (squash) May 11, 2026 18:14
@osipxd osipxd merged commit 13ef4d5 into main May 12, 2026
18 of 21 checks passed
@osipxd osipxd deleted the osipxd/darwin-frame-too-big branch May 12, 2026 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants