astrid-runtime/astrid · error

MCP gateway control frame is missing or too large

Error message

MCP gateway control frame is missing or too large

What it means

read_bounded_line reads the control-frame bytes until a newline or its size bound; if neither the terminating \n nor the bound is reached (stream ended early or frame exceeded the limit without delimiter), it bails with this message.

Solutions

  1. Restart the gateway and retry the control operation — the stream likely died mid-frame
  2. Check gateway logs for a crash or panic around the request time
  3. Confirm nothing else is writing to the gateway socket (stale listener, another process)
  4. If frames legitimately grow, raise the frame size bound in the client and gateway together

Example fix

// before: single attempt
let ack = request_gateway_control(...).await?;
// after: retry once on truncated frame
let ack = match request_gateway_control(...).await {
    Err(e) if e.to_string().contains("missing or too large") => {
        restart_gateway().await?;
        request_gateway_control(...).await?
    },
    other => other?,
};
Defensive patterns

Strategy: retry

Validate before calling

// verify the socket answers before sending control frames
let outcome = connect_outcome(&gateway_socket_path()?).await?;
anyhow::ensure!(!matches!(outcome, ConnectOutcome::Absent), "gateway socket absent");

Try / catch

match request_gateway_control(...).await {
    Err(e) if e.to_string().contains("missing or too large") => {
        restart_gateway().await?;
        request_gateway_control(...).await?
    },
    other => other?,
}

Prevention

When it happens

Trigger: The gateway closes the control connection before sending a newline, or sends a frame larger than the bounded limit without a delimiter, while request_gateway_control reads the ack.

Common situations: Gateway crashed mid-response; a non-gateway process or error text wrote to the socket; a protocol mismatch producing an oversized undelimited blob.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/7b7f29bbdff84d3f. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-cli/src/commands/mcp/lifecycle.rs:705

    Ok(ack)
}

pub(crate) async fn read_bounded_line<R>(reader: &mut R) -> Result<Vec<u8>>
where
    R: tokio::io::AsyncRead + Unpin,
{
    let mut line = Vec::new();
    for _ in 0..=MAX_CONTROL_BYTES {
        let byte = reader
            .read_u8()
            .await
            .context("failed to read control frame")?;
        if byte == b'\n' {
            return Ok(line);
        }
        line.push(byte);
    }
    anyhow::bail!("MCP gateway control frame is missing or too large")
}

async fn remove_dead_gateway_markers(record: &GatewayReady) -> Result<()> {
    if crate::commands::daemon_control::is_process_alive(record.pid) {
        anyhow::bail!(
            "shutdown stage gateway.process_reap: PID {} is still alive",
            record.pid
        );
    }
    let lifecycle = try_acquire_gateway_lifecycle()?;
    let Some(lifecycle) = lifecycle else {
        anyhow::bail!(
            "shutdown stage gateway.lifecycle_fence: a successor gateway lifecycle remains active"
        );
    };
    let socket = gateway_socket_path()?;
    match astrid_core::local_transport::connect_outcome(&socket)
        .await

View on GitHub (pinned to affd8760f4)