BloopAI/vibe-kanban · error

invalid relay WS sequence: expected {expected_seq}, got {}

Error message

invalid relay WS sequence: expected {expected_seq}, got {}

What it means

Signed WS envelopes carry a monotonically increasing sequence number; decode() requires the inbound envelope's seq to equal inbound_seq + 1 to detect replay, drops, or reordering under the negotiated crypto session. Any other sequence is rejected.

Source

Thrown at crates/relay-ws/src/crypto.rs:95

        }
    }

    /// Verify a signed JSON envelope and deserialize it back into a frame.
    ///
    /// Checks the Ed25519 signature and enforces monotonic sequence ordering.
    pub(crate) fn decode(&mut self, raw: &[u8]) -> anyhow::Result<RelayWsFrame> {
        use anyhow::Context as _;

        let envelope: SignedWsEnvelope =
            serde_json::from_slice(raw).context("invalid relay WS envelope JSON")?;

        if envelope.version != ENVELOPE_VERSION {
            anyhow::bail!("unsupported relay WS envelope version");
        }

        let expected_seq = self.inbound_seq.saturating_add(1);
        if envelope.seq != expected_seq {
            anyhow::bail!(
                "invalid relay WS sequence: expected {expected_seq}, got {}",
                envelope.seq
            );
        }

        let payload = BASE64_STANDARD
            .decode(&envelope.payload_b64)
            .context("invalid relay WS payload")?;

        let signing_input = ws_signing_input(
            &self.request_signature,
            envelope.seq,
            envelope.msg_type,
            &payload,
        );
        let signature_bytes = BASE64_STANDARD
            .decode(&envelope.signature_b64)
            .context("invalid relay WS frame signature encoding")?;

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Ensure envelopes are delivered in order and exactly once over the session
  2. Re-establish/re-key the crypto session after reconnects so both seq counters reset
  3. Drop duplicates before calling decode(); check envelope.seq vs inbound_seq before processing
  4. Debug which seq was received vs expected in the log message

Example fix

// before
let _ = crypto.decode(envelope_seq_5)?; // after already decoding seq 4, expected 5... got 5 fine; got 7 -> bail
let _ = crypto.decode(envelope_seq_7)?;
// after
let seq = envelope.seq;
if seq != crypto.expected_inbound_seq() { crypto.reset_session()?; }
let _ = crypto.decode(envelope)?;
Defensive patterns

Strategy: retry

Validate before calling

if envelope.seq != crypto.expected_inbound_seq() { // buffer or request retransmit before decode }

Try / catch

match crypto.decode(raw) { Err(e) if e.to_string().starts_with("invalid relay WS sequence") => resync_or_rekey_session(), other => other? }

Prevention

When it happens

Trigger: Second call to decode() on a fresh CryptoSession reusing an old first envelope; out-of-order WS message delivery; duplicated envelope delivery; a peer restarting and resetting its seq counter while this side retains state.

Common situations: Message replay/reordering across flaky transports; reconnect logic replaying buffered envelopes; mismatched session pairing where two encoders feed one decoder.

Related errors


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/4a0806ea22b7b938. Report an issue: GitHub.