apple/pkl · error · ProtocolException

Unexpected incoming request message: ${msg}

Error message

Unexpected incoming request message: ${msg}

What it means

runTransport also registers a handler for incoming request messages from the reader; the host never expects to serve requests to the reader, so any incoming request is a protocol violation and throws ProtocolException wrapped in a RuntimeException in the rxThread. This protects the host from readers that misuse the request channel.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/externalreader/ExternalReaderProcessImpl.java:149

      rxThread.start();

      return transport;
    }
  }

  /**
   * Runs the underlying message transport so it can receive responses from the child process.
   *
   * <p>Blocks until the underlying transport is closed.
   */
  private void runTransport(MessageTransport transport) {
    try {
      transport.start(
          (msg) -> {
            throw new ProtocolException("Unexpected incoming one-way message: " + msg);
          },
          (msg) -> {
            throw new ProtocolException("Unexpected incoming request message: " + msg);
          });
    } catch (ProtocolException | IOException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public void close() {
    synchronized (lock) {
      if (closed) return;
      closed = true;

      try {
        if (transport != null && process != null && process.isAlive()) {
          transport.send(new CloseExternalProcess());
          process.waitFor(CLOSE_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
        }
      } catch (Exception ignored) {

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Align protocol versions between pkl-core and the external reader binary
  2. Fix the reader implementation to send only one-way messages/responses, never requests
  3. Log the offending message to identify which request type was sent
  4. Capture a transport trace to check for framing desynchronization
Defensive patterns

Strategy: try-catch

Try / catch

try {
  reader.use { ... }
} catch (RuntimeException e) {
  if (e.getCause() instanceof ProtocolException pe && pe.getMessage().startsWith("Unexpected incoming request message")) {
    // reader sent a request; align protocol versions or fix the reader
  }
}

Prevention

When it happens

Trigger: The external reader process sends a request-type message to the host — e.g. a buggy or newer reader expecting bidirectional requests, or stream corruption making a reply parse as a request.

Common situations: Protocol version mismatch between pkl-core and the reader binary, custom reader implementations issuing requests, desynchronized framing after an error.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/dcf8e4d5da340415. Report an issue: GitHub.