Where communities thrive

  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
Repo info
  • Oct 25 17:46

    mergify[bot] on master

    Update fs2-core, fs2-io, ... to… Merge pull request #1162 from s… (compare)

  • Oct 25 17:46
    mergify[bot] closed #1162
  • Oct 25 17:13
    mergify[bot] labeled #1162
  • Oct 25 17:12
    scala-steward opened #1162
  • Oct 25 15:10
    swoogles opened #1161
  • Oct 25 08:52

    adamw on master

    Docs (compare)

  • Oct 25 07:25
    bartekzylinski synchronize #1154
  • Oct 25 07:25

    bartekzylinski on auto-decompression-turning

    Disable gzip serving tests for … (compare)

  • Oct 24 19:25

    mergify[bot] on master

    Update scribe to 3.6.2 Merge pull request #1160 from s… (compare)

  • Oct 24 19:25
    mergify[bot] closed #1160
  • Oct 24 18:52
    mergify[bot] labeled #1160
  • Oct 24 18:52
    scala-steward opened #1160
  • Oct 23 21:36

    mergify[bot] on master

    Update fs2-core, fs2-io, ... to… Merge pull request #1159 from s… (compare)

  • Oct 23 21:36
    mergify[bot] closed #1159
  • Oct 23 21:02
    mergify[bot] labeled #1159
  • Oct 23 21:01
    scala-steward opened #1159
  • Oct 22 16:57
    adamw commented #1158
  • Oct 22 16:57

    adamw on master

    Fix broken link to the Websocke… Merge pull request #1158 from K… (compare)

  • Oct 22 16:57
    adamw closed #1158
  • Oct 22 16:43
    KRoLer opened #1158
So, did I get it right that I have to flatMap backend whenever I send any requests?
it was not clearly explained in docs (or at least I did not get it)

I was wondering what was the best way to handle error with STTP and the ZIO backend.
The send method returns Throwable with (as explained in the doc) known error converted to SttpClientException.
Addind to that the circe decoding exception in a ResponseException, this become really tedious to deal with.
Do you have any recommendation ?
Let's assume the following piece of code:

        override def send[T](
            request: Request[MatrixResponse[T], Any]
        ): ZIO[Any, ResponseException[ResponseError, io.circe.Error], T] = {
          for {
            result <- sendRequest(request).provide(client) // Throwable (low level error, network error, ...)
            json <- ZIO.fromEither(result.body) // ResponseException (API error OR circe error)
          } yield json

It does not compile because (sendRequest an alias to STTP send) sendRequest can fail with Throwable.
I would like to avoid forwarding this Throwable up to the caller, because it's confusing and does not make the type signature very useful.
Another solution would be to "flatten" those error (network error, api error and serialization errors) by creating an ADT to wrap them, is it a good solution ?

5 replies

I'm writing a VCR lib with sttp which means I have to wrap any HTTP backend in a general way and have it still work. One thing I'm struggling with is converting an arbitrary response T to a String. I have this dirty hack currently that I want to get rid of:

Is there a typeclass I missed or some other mechanism to handle this? Any hints where to look would be appreciated 🙂

7 replies
Jakub Kozłowski
hello there, is there a way to match the body text in a fake backend? In particular, I want to ensure a particular field is present in the body when decoded as a JSON object, but if I'm able to get the body as a string I'll be fine from that point
1 reply
@reibitto: you probably don't want to go to string but to a stream of bytes
2 replies
since users don't necessarily have to send utf8 strings
kinda weird that it's a generic T with no constraints but ideally you'd want something with an encoder/decoder typeclass constraint - these/one of these are probably included in the request's description of the response?
Brandon G
Is Sttp supposed to wrap timeout exceptions arising from readTimeouts? I'm noticing that connectionTimeouts are properly wrapped, but readTimeouts throw unwrapped.
1 reply
Anirudh Vyas

hi there, For payload responses that are very large, I am running into :

12:01:32.294 [ERROR] o.a.n.h.WebSocketHandler - null
java.lang.NullPointerException: null
    at org.asynchttpclient.netty.channel.Channels.getAttribute(Channels.java:31)
    at org.asynchttpclient.netty.request.NettyRequestSender.abort(NettyRequestSender.java:467)
    at org.asynchttpclient.netty.handler.AsyncHttpClientHandler.exceptionCaught(AsyncHttpClientHandler.java:201)
    at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:302)
    at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:281)
    at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:273)
    at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:143)

unsure what needs to be done there - I am using AsyncMonix handler for Websockets.

5 replies
I may have response frames/messages in Megs at times - I cannot receive streams etc. since this is more of a black box testing
 implicit val scheduler: Scheduler = Scheduler.global
        .flatMap { backend =>
              asWebSocket { (f: WebSocket[Task]) =>
                val observable = Observable
                  .repeatEvalF(f.receiveText()) // repeatedly call receive text to grab messages.
                  .dump("Incoming Msg")         // dumps message to println (can pass logger here)
                  .takeWhileInclusive { e =>    // take all values until condition is met + also include value where
                    // where condition is not met for the first time (for us this would be till completion)
                    println(s"is condition met for $e ${terminateOn(e)}")
                    !terminateOn(e) // negative to accumulate all messages.
                f.sendText(msg) *> observable.toListL // toListL transforms to a Task.pure(List[String])
thats my sample code
Octav Zaharia
hi, where is the sttp version set ?
5 replies
Akshay Sachdeva

Hi...so stack is
val http4s = "0.21.22"
val tapir = "0.18.0-M5"

val request = SttpClientInterpreter.toRequestThrowDecoderFailures(makeCall, config.server.externalApi.some)

        val response = request

where makeCall is an endpoint like

val makeCall = endpoint.get

Everything looks good and all of the query Params get applied but I see that the request looks like https://api.blah.com/?param1= and so on...essentially with a slash after the external api uri and before the question mark for the query parameters. I have confirmed that the externalAPI does not have a trailing slash. Am I missing something obvious here? Thanks in advance for any help

2 replies
Is there a reason why async-http-client-backend-zio isn't released for 3.0.0-RC1 and/or -RC2?
1 reply
1.0.5 was released for 3.0.0-RC1, and I believe 1.0.6 is released for 3.0.0-RC2.
dev.zio:zio_3.0.0-RC2:1.0.6 and dev.zio:zio_3.0.0-RC1:1.0.5
Adam Warski
ah, well it wasn't at the moment of the release :) I'll try to re-enable before the next one

hi. i'm trying to write a function to execute requests using an SttpBackend[Future, Any], but i keep running into this error on compilation:

Cannot prove that Any with sttp.capabilities.Effect[scala.concurrent.Future] <:< Nothing with Any.
[error]         .send(backend)
[error]              ^

this is with version 3.2.3 of the library

2 replies
Hey! I've moved an existing project to a new machine with java 11 & latest version of intelliJ - now it won't find the basicRequest anymore in my IDE. Although I do have import sttp.client3._ - are there any special/hidden settings I need to make in intelliJ ??? I'm pretty puzzled ...
2 replies
@adamw: sttp-shared 1.2.2 is missing for 3.0.0-RC2 – but Scala 3 was reenabled in the build.sbt before that release. Did something go wrong? Will it be out soon?
1 reply
The zio one, I mean.
I need com.softwaremill.sttp.shared:zio_3.0.0-RC2:1.2.2 in an attempt to see if I can compile the tapir zio integrations for Scala 3 (with 2.13.5 core), it's the only dependency I am missing.
Joshua Portway
Hi - perhaps I'm misunderstanding something here, but is there an effectful version of asWebSocketStreamAlways ? The "pipe" required by this seems to have to be a simple function from an input stream to an output stream, but with ZIO (for instance, haven't tried other libraries) it is often not possible to create a stream without running an effect.
8 replies
several stream operations (for instance, partitioning a stream) don't produce a stream directly, but return an effect that produces the stream. But the "pipe" funtion required by asWebSocketStream needs to be pure - so there is no way to run the effect
Joshua Portway
Unless I'm misunderstanding something, this seems to severely limit the possibilities of what can be done with streams - basically it looks like I can only do simple mapping and transformations and not anything else that might itself require an IO type effect. Is this right?
Odd, it's there now, it didn't show earlier when I looked up at search.maven.org.
Sergei Kharchikov
Hey! Is there a way to create AsyncHttpClientZioBackend.layer() but with enabled logging?
6 replies
How can I convert non-literal String into Uri ? Just uri"""$someNonLiteral""" ?
2 replies
Paweł Kaczor

Hello! I'm processing UTF-8 with BOM encoded json at the client side in the following way:


  def myResponse = {

Is there a simpler way to do it ? (to remove initial character from the json string) ?

1 reply
Thijs Broersen
I am trying to generate a client from an OpenAPI-spec and it looks like it is fixed to the old sttp.client and not sttp.client3, while readthedocs clearly have client3 in their examples. I cannot get it to generate client3 code, is this correct?
2 replies


am I correct in assuming that SttpbackendStub does not support websocket streams?

9 replies
basing this on case ResponseAsWebSocketStream(_, _) => None in tryAdjustResponseBody
Zdenek Farana
Hey, does anyone have multipart/mixed response deserializer implementation by any chance? 😅
2 replies
@adamw tapir-0.18.0-M8 wasn't published to sonatype
1 reply
Matt Smith
Hi, how can I catch network failures and make them a future instead? I'm using the Java 11 HttpClient backend. I've tried this but the exception doesn't get caught and it ends up stopping the whole application:
    try {
    } catch {
      case e: SttpClientException.ConnectException => Future.failed(e)
3 replies
Felix Dietze
Hi, I'm trying to use FetchCatsBackend[IO] with ScalaJS, but I'm getting this error message, what am I missing?
import sttp.client3.impl.cats.FetchCatsBackend
import cats.effect._
import sttp.client3._

  implicit val ec: scala.concurrent.ExecutionContext =
  implicit val contextShift: ContextShift[IO]        = IO.contextShift(ec)

  // https://sttp.softwaremill.com/en/latest/backends/javascript/fetch.html?highlight=fetch#node-js
  val g         = scalajs.js.Dynamic.global.globalThis
  val nodeFetch = g.require("node-fetch")
  g.fetch = nodeFetch
  g.Headers = nodeFetch.Headers
  g.Request = nodeFetch.Request

  val sttpBackend = FetchCatsBackend[IO]()
[error]      could not find implicit value for evidence parameter of type cats.effect.kernel.Async[cats.effect.IO] (Could not find an instance of Monad for cats.effect.IO)
[error]      Error occurred in an application involving default arguments.
[error]      L59:   val sttpBackend = FetchCatsBackend[IO]()
[error]                                                   ^
Felix Dietze
solved it, I'm working with Cats 2, where the latest sttp release defaults to Cats 3
Felix Dietze
Is node-fetch the only backend for scalajs? I can't get it to work... :(
Seems to be a problem with abortcontroller
1 reply

I'm trying to write a generic interface for all my case class that inherits from the same trait, the current trait looks like that

import NodeSerialization.{nodeDecoder, nodeEncoder} 

trait CustomEndpointForNode[T <: Node] {
  implicit private def ct: ClassTag[T] = implicitly[ClassTag[T]]

  def getEndpointDefinition: Endpoint[NodeQueryParams, String, Seq[T], Any]

  def postEndpointDefinition: Endpoint[T, String, T, Any]

  def getBasePath: String
  def getEndpointDescription  = "Get given endpoint type"
  def postEndpointDescription = "Post new given endpoint type"

  def getEndpointDefinition: Endpoint[NodeQueryParams, String, Seq[T], Any] =

  def postEndpointDefinition: Endpoint[T, String, T, Any] =

  def getAllEndpointDefinitions: List[Endpoint[_, _, _, _]] = List(getEndpointDefinition, postEndpointDefinition)

  def getItems(params: NodeQueryParams): Future[Either[String, Seq[T]]]
  def postItem(item: T): Future[Either[String, T]]

  def allRoutes(): Route = {

Note that in the jsonBody I use a serialization for the trait Node and not for a given T, this is because the serialization is done automatically using Circe which only provided a Decoder/Encoder for the trait and not for indiviual case classes . is there a way, given the ClassTag[T] to filter (similar to collect) only instances of T in order to retrieve a Seq[T] instead of Seq[Node] ?

thanks !

8 replies
Krzysztof Piszko
Hello. I'm using SttpBackendOptions to setup a proxy, but I'd like to use this proxy only for specific hosts. Unfortunately, it seems that SttpBackendOptions only supports nonProxyHosts. Before I write an issue and try to implement this, I wanted to make sure that I'm not missing something that's implemented already. So, anybody knows about something like nonProxyHosts opposite?
3 replies
Tim Pigden

Hi, I'm on 2.2.9. I have a problem that websocket frame size is too small

io.netty.handler.codec.http.websocketx.CorruptedWebSocketFrameException: Max frame length of 10240 has been exceeded.

I'm using zio async backend. How do I change the frame length?

Tim Pigden
Never mind fixed it:
def bigBuffer = {
    val config = new DefaultAsyncHttpClientConfig.Builder()
      .setWebSocketMaxFrameSize(1024 * 1024 * 2) 
Joshua Portway
Hi - I'm trying to Stub a Websocket, but as soon as I try to open the websocket using the stub backend the websocket terminates immediately - my websocket code never even seems to receieve the initial message. The actual code itself seems to work fine when using a real live backend, it only fails with the stubbed backend. Here is my stubbing code :
        val backend = HttpClientZioBackend.stubLayer

        val webSocketStub = WebSocketStub
            List(WebSocketFrame.text("Hello from the server!"))
          .thenRespond{ _ => List(WebSocketFrame.text("nothing more to say here")) }

        val stubEffect:URIO[SttpClientStubbing with Logging, Unit]  = for {
          _ <- log.info("stubbing")
          _ <- whenAnyRequest.thenRespond(webSocketStub)
        } yield ()
Joshua Portway

Here is my send code:

send(basicRequest.get(uri"wss://website.com/blah").response(responseType)).tap(res => log.info(s"websocket request fibre terminated with $res")).fork

When using a normal backend, that send task will keep going until the websocket gets closed. But when I use the stubbed backend it seems to close immediately and I get this logged :

websocket request fibre terminated with Response(sttp.ws.testing.WebSocketStub@7ce08c7f,200,OK,List(),List(),RequestMetadata(GET,http://example.com,List()))
Joshua Portway
I still have no joy with the problem I described above - as far as I can tell I'm following the documentation for stubbing pretty much exactly and no amount of blind fiddling seems to produce a different result. When the stubbed backend returns a WebSocketStub the request seems to end immediately with the WebsocketStub itself as the body of the response. Should I file a bug for this, or am I completely misunderstanding something?
7 replies
Jonathan Neufeld
I'm running into a dependency conflict and trying to sort it out, what version of Sttp model is supposed to pair with Sttp core 2.2.9?
3 replies
Jonathan Neufeld
Ok I think I'm officially in JAR hell w.r.t. Sttp model / core