apple/pkl · error · ProtocolException

Cannot receive one-way messages before transport start.

Error message

Cannot receive one-way messages before transport start.

What it means

(Same family as 121.) The default handlers of AbstractMessageTransport throw ProtocolException for any incoming message before start() runs. This entry covers the one-way message path: a OneWay message was delivered while the transport was still in its pre-start state.

Solutions

  1. Ensure start() is invoked immediately after constructing the transport and before connecting
  2. Synchronize transport startup with peer connection establishment
  3. Log transport lifecycle to confirm handler registration happens before first inbound message

Example fix

// before
MessageTransports.AbstractMessageTransport t = new MyTransport(logger);
t.accept(inbound); // throws
// after
MyTransport t = new MyTransport(logger);
t.start();
t.accept(inbound);
Defensive patterns

Strategy: validation

Validate before calling

if (!started) { LOG.error("one-way message dropped: transport not started"); return; }

Type guard

null

Try / catch

try { accept(msg); } catch (ProtocolException e) { if (e.getMessage().contains("before transport start")) { transport.start(); } else throw e; }

Prevention

When it happens

Trigger: oneWayHandler.handleOneWay(msg) is invoked in accept() with the default handler still installed, i.e. start() was never called before messages flowed.

Common situations: Transport wiring races in evaluator hosts; external readers sending notifications immediately after handshake; missing start() call in custom MessageTransport implementations.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/messaging/MessageTransports.java:131

    @Override
    protected void doSend(Message message) throws ProtocolException, IOException {
      var other = this.other;
      assert other != null;
      other.accept(message);
    }

    public void setOther(DirectMessageTransport other) {
      this.other = other;
    }
  }

  public abstract static class AbstractMessageTransport implements MessageTransport {

    private final Logger logger;
    private MessageTransport.OneWayHandler oneWayHandler =
        (msg) -> {
          throw new ProtocolException("Cannot receive one-way messages before transport start.");
        };
    private MessageTransport.RequestHandler requestHandler =
        (msg) -> {
          throw new ProtocolException("Cannot receive request messages before transport start.");
        };
    private final Map<Long, ResponseHandler> responseHandlers = new ConcurrentHashMap<>();

    protected AbstractMessageTransport(Logger logger) {
      this.logger = logger;
    }

    protected void log(String message, Object... args) {
      var formatter = new MessageFormat(message);
      logger.log(formatter.format(args));
    }

    protected abstract void doStart() throws ProtocolException, IOException;

View on GitHub (pinned to f3efcbfc9b)