jdx/mise · error

the first agent request must be hello

Error message

the first agent request must be hello

What it means

handle_connection implements a line-delimited request protocol with a mandatory handshake: the first request on a fresh stream must be Hello (a version mismatch gets a dedicated "cache client X does not match agent Y" Error response first). Any other first message — Lookup, Record, garbage — bails with this error and the connection ends.

Source

Thrown at crates/mise-cache-core/src/agent.rs:1767

                    },
                )
                .await?;
                return Ok(());
            }
            AgentRequest::Hello { client_version, .. } => {
                send_response(
                    &mut writer,
                    &AgentResponse::Error {
                        message: format!(
                            "cache client {client_version} does not match agent {}",
                            self.version
                        ),
                    },
                )
                .await?;
                return Ok(());
            }
            _ => bail!("the first agent request must be hello"),
        }
        send_response(
            &mut writer,
            &AgentResponse::Hello {
                protocol: AGENT_PROTOCOL_VERSION,
                agent_version: self.version.to_string(),
            },
        )
        .await?;

        while let Some(line) = lines.next_line().await? {
            let response = match serde_json::from_str(&line) {
                Ok(request) => self.respond(request).await,
                Err(error) => AgentResponse::Error {
                    message: format!("invalid agent request: {error}"),
                },
            };
            send_response(&mut writer, &response).await?;

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Send the Hello request as the very first line, matching AgentRequest's serde shape with a client_version field
  2. Read the Hello response: a version-mismatch Error names both client and agent versions — align them
  3. Upgrade the client to a build whose protocol matches the agent

Example fix

// before
writeln!(writer, "{}", serde_json::to_string(&AgentRequest::Lookup { .. })?)?;
// after
writeln!(writer, "{}", serde_json::to_string(&AgentRequest::Hello { client_version })?)?;
let _hello = read_response(&mut reader).await?;
writeln!(writer, "{}", serde_json::to_string(&AgentRequest::Lookup { .. })?)?;
Defensive patterns

Strategy: validation

Validate before calling

// Always open the session with Hello and consume the reply before any request
let hello = serde_json::to_string(&AgentRequest::Hello { client_version })?;
writeln!(writer, "{hello}")?; writer.flush().await?;
match read_response(&mut reader).await? {
    AgentResponse::Hello { agent_version, .. } => { /* check version compatibility */ }
    AgentResponse::Error { message } => bail!("handshake rejected: {message}"),
    _ => bail!("unexpected first response"),
}

Prevention

When it happens

Trigger: A client sending requests before Hello; a raw probe (nc/curl) writing a non-Hello line; a client whose serde enum encoding deserializes into the wrong variant; a client skipping handshake by bug.

Common situations: Hand-rolled or out-of-date clients; health checks poking the socket with arbitrary bytes; protocol version skew between client and agent builds.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/f0408db47df30842. Report an issue: GitHub.