akka / akka/akka-http

formFields and Error in stage [unknown-operation]: Promise already completed

Open
#73 27 comments 1 reaction 0 assignees View on GitHub
1 - triaged bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.