URLSessionWebSocketTask failed handle large handles binary data frames

in the local testing, if the binary data length is small like 300 bytes, then it can send binary data success, but if the data length is more that 3000 bytes, then it will failed and print the error like in the screen capture

Answered by DTS Engineer in 826517022

Normally I recommend that you not use URLSession for WebSocket, but instead go straight to Network framework. See TN3151 Choosing the right networking API. That might be the right answer here as well, but for non-obvious reasons.

The inflate returned data error log entry [1] suggests that the root cause of this problem is a failure to decode the data as it was compressed by the server. RFC 7692 describes how that’s set up. It’s an optional feature that the client has to request via the Sec-WebSocket-Extensions header.

Curiously, if you start a WebSocket connection with Network framework, you don’t get this header:

GET / HTTP/1.1
Host: 127.0.0.1
Sec-WebSocket-Version: 13
Upgrade: WebSocket
Sec-WebSocket-Key: XGMlXE+VvSjiIA589/oLDw==
Connection: Upgrade

But if you start it with URLSession you do:

GET / HTTP/1.1
Host: 127.0.0.1:12345
User-Agent: xxs (unknown version) CFNetwork/3826.400.120 Darwin/24.3.0
Sec-WebSocket-Key: piYv23+neitg1x+hVbPYvw==
Sec-WebSocket-Version: 13
Upgrade: websocket
Accept: */*
Sec-WebSocket-Extensions: permessage-deflate
Accept-Language: en-GB,en;q=0.9
Accept-Encoding: gzip, deflate
Connection: Upgrade

That suggests that URLSession has opted into this somehow, but there are no Network framework APIs to do that. I suspect it’s using SPI [2].

There are two possibilities here

  • Either Network framework’s compression support is broken.

  • Or the equivalent support on the server is broken.

It’s hard to tell based on the info we have available. To investigate this further one would need to be able to see the compressed bytes. And that’s hard to do if the server is using TLS, as most do these days.

If you can create a test project that reproduces this issue, it’d be worthwhile filing a bug about this and attaching your project. And if you do file that bug, please post your bug number, just for the record.

As to how you work around this, I see a couple of options:

  • If you have control over the server, you could disable compression on that side.

  • You could switch to Network framework, where compression is off by default.

If you’re looking to get started with WebSocket in Network framework, I posted some examples to this thread.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] It’s much easier to quote log entries if you post them as text rather than images. See tip 6 in Quinn’s Top Ten DevForums Tips.

[2] As defined here.

Normally I recommend that you not use URLSession for WebSocket, but instead go straight to Network framework. See TN3151 Choosing the right networking API. That might be the right answer here as well, but for non-obvious reasons.

The inflate returned data error log entry [1] suggests that the root cause of this problem is a failure to decode the data as it was compressed by the server. RFC 7692 describes how that’s set up. It’s an optional feature that the client has to request via the Sec-WebSocket-Extensions header.

Curiously, if you start a WebSocket connection with Network framework, you don’t get this header:

GET / HTTP/1.1
Host: 127.0.0.1
Sec-WebSocket-Version: 13
Upgrade: WebSocket
Sec-WebSocket-Key: XGMlXE+VvSjiIA589/oLDw==
Connection: Upgrade

But if you start it with URLSession you do:

GET / HTTP/1.1
Host: 127.0.0.1:12345
User-Agent: xxs (unknown version) CFNetwork/3826.400.120 Darwin/24.3.0
Sec-WebSocket-Key: piYv23+neitg1x+hVbPYvw==
Sec-WebSocket-Version: 13
Upgrade: websocket
Accept: */*
Sec-WebSocket-Extensions: permessage-deflate
Accept-Language: en-GB,en;q=0.9
Accept-Encoding: gzip, deflate
Connection: Upgrade

That suggests that URLSession has opted into this somehow, but there are no Network framework APIs to do that. I suspect it’s using SPI [2].

There are two possibilities here

  • Either Network framework’s compression support is broken.

  • Or the equivalent support on the server is broken.

It’s hard to tell based on the info we have available. To investigate this further one would need to be able to see the compressed bytes. And that’s hard to do if the server is using TLS, as most do these days.

If you can create a test project that reproduces this issue, it’d be worthwhile filing a bug about this and attaching your project. And if you do file that bug, please post your bug number, just for the record.

As to how you work around this, I see a couple of options:

  • If you have control over the server, you could disable compression on that side.

  • You could switch to Network framework, where compression is off by default.

If you’re looking to get started with WebSocket in Network framework, I posted some examples to this thread.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] It’s much easier to quote log entries if you post them as text rather than images. See tip 6 in Quinn’s Top Ten DevForums Tips.

[2] As defined here.

You wrote:

whether this is a correct way?

“Correct” is such a loaded term (-:

AFAICT this approach will work. There’s logic within URLSession such that, if you set the Sec-WebSocket-Extensions field to anything, it’ll avoid overriding the value you set.

ps It’s better to reply as a reply, rather than in the comments; see Quinn’s Top Ten DevForums Tips for this and other titbits.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

URLSessionWebSocketTask failed handle large handles binary data frames
 
 
Q