formFields and Error in stage [unknown-operation]: Promise already completed
- Dominant language
- Scala
- Stars
- 1.4k
- Forks
- 584
- Avg merge
- 14h 33m
- Merged PRs (30d)
- 24
Description
**Issue by [s12v](https://github.com/s12v)**
_Wednesday Mar 09, 2016 at 12:22 GMT_
_Originally opened as https://github.com/akka/akka/issues/19981_
---
I'm having intermittent exception when using akka-http and `formFields`:
```
ERROR] [03/09/2016 13:14:34.252] [SNS-akka.actor.default-dispatcher-4] [akka://SNS/user/StreamSupervisor-0/flow-3-0-unknown-operation] Error in stage [unknown-operation]: Promise already completed.
java.lang.IllegalStateException: Promise already completed.
at scala.concurrent.Promise$class.complete(Promise.scala:55)
at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153)
at scala.concurrent.Promise$class.failure(Promise.scala:104)
at scala.concurrent.impl.Promise$DefaultPromise.failure(Promise.scala:153)
at akka.http.impl.util.StreamUtils$$anon$2.onUpstreamFailure(StreamUtils.scala:76)
at akka.http.impl.util.StreamUtils$$anon$2.onUpstreamFailure(StreamUtils.scala:69)
at akka.stream.stage.AbstractStage$PushPullGraphLogic$$anon$1.onUpstreamFailure(Stage.scala:62)
at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:621)
at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:535)
at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:443)
at akka.stream.impl.fusing.GraphInterpreterShell.init(ActorGraphInterpreter.scala:364)
at akka.stream.impl.fusing.ActorGraphInterpreter.tryInit(ActorGraphInterpreter.scala:502)
at akka.stream.impl.fusing.ActorGraphInterpreter.preStart(ActorGraphInterpreter.scala:539)
at akka.actor.Actor$class.aroundPreStart(Actor.scala:485)
at akka.stream.impl.fusing.ActorGraphInterpreter.aroundPreStart(ActorGraphInterpreter.scala:493)
at akka.actor.ActorCell.create(ActorCell.scala:590)
at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:461)
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:483)
at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:282)
at akka.dispatch.Mailbox.run(Mailbox.scala:223)
at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
```
It's one of 10 or 100 requests, pretty random, other requests are fine.
This is the code (I think only `handler` is relevant):
``` scala
package me.snov.sns
import java.util.concurrent.TimeUnit
import akka.actor.ActorSystem
import akka.event.{Logging, LoggingAdapter}
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpResponse}
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import akka.util.Timeout
import me.snov.sns.api._
import me.snov.sns.utils.Config
import scala.concurrent.ExecutionContext
object Main extends App with Config with HealthCheck {
implicit val system = ActorSystem("SNS")
implicit val executor: ExecutionContext = system.dispatcher
implicit val materializer: ActorMaterializer = ActorMaterializer()
implicit val logger: LoggingAdapter = Logging(system, getClass)
implicit val timeout = new Timeout(1000, TimeUnit.MILLISECONDS)
val xml =
foo
bar
val r = HttpResponse(
entity = HttpEntity(ContentTypes.`text/xml(UTF-8)`, scala.xml.Utility.trim(xml).toString())
)
Http().bindAndHandle(
handler = logRequestResult("akka-http")(
pathSingleSlash {
formFields('Action ! "CreateTopic", 'Name) { (name) =>
complete(r)
}
}
),
interface = config.getString("http.interface"),
port = config.getInt("http.port")
)
}
```
If I remove `formFields` (and have only `pathSingleSlash {complete(r)}`) the issue is gone.
What can be a reason, am I doing something wrong? A bug?
Contributor guide
Research direction
Reproduce the supplied akka-http handler with repeated formFields requests, then inspect the formFields entry point and akka.http.impl.util.StreamUtils.scala around line 76. Trace how upstream failures complete the promise and verify that the intermittent Promise already completed error no longer occurs, with coverage for the failing request path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- scala
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100