ekzhang/bore · error

expected authentication challenge, but no secret was…

Error message

expected authentication challenge, but no secret was required

What it means

During `Authenticator::client_handshake`, the client expects the server's first message to be a `ServerMessage::Challenge`, but received something else (typically a `Hello`) or nothing. This means the server did not request authentication, yet the client was configured with a secret.

Solutions

  1. Remove `--secret` from the client command, since the server does not require authentication: `bore local <port> --to <host>`.
  2. If auth is desired, restart the server with the same secret: `bore server --secret mysecret`.
  3. Verify you are connecting to the intended host/port and that both sides run compatible bore versions.

Example fix

// before (server started without --secret)
bore local 3000 --to bore.example.com --secret mysecret
// after
bore local 3000 --to bore.example.com
Defensive patterns

Strategy: validation

Validate before calling

// Only configure a client secret if the server actually uses auth
if client_secret.is_some() && !server_uses_secret {
    bail!("server does not require a secret; omit --secret");
}

Try / catch

match Client::new(...).await {
    Err(e) if e.to_string().contains("no secret was required") => retry_without_secret(),
    other => other,
}

Prevention

When it happens

Trigger: Calling `client_handshake` (i.e. constructing a client with a secret) against a server that was started without `--secret`; the server immediately sends `Hello` instead of a challenge; the connection EOFs or times out before a challenge arrives.

Common situations: User passes `--secret` on the client while the server runs without a secret; server upgraded/downgraded to a version without auth support; connecting to the wrong port or a different bore instance than intended.

Understand the failure class

Related errors


AI-assisted analysis of ekzhang/bore@00a735a899 (2026-09-08). Data as JSON: /api/errors/9ce0f0cb3637cb72. Report an issue: GitHub.

Appendix: source

Thrown at src/auth.rs:73

        let challenge = Uuid::new_v4();
        stream.send(ServerMessage::Challenge(challenge)).await?;
        match stream.recv_timeout().await? {
            Some(ClientMessage::Authenticate(tag)) => {
                ensure!(self.validate(&challenge, &tag), "invalid secret");
                Ok(())
            }
            _ => bail!("server requires secret, but no secret was provided"),
        }
    }

    /// As the client, answer a challenge to attempt to authenticate with the server.
    pub async fn client_handshake<T: AsyncRead + AsyncWrite + Unpin>(
        &self,
        stream: &mut Delimited<T>,
    ) -> Result<()> {
        let challenge = match stream.recv_timeout().await? {
            Some(ServerMessage::Challenge(challenge)) => challenge,
            _ => bail!("expected authentication challenge, but no secret was required"),
        };
        let tag = self.answer(&challenge);
        stream.send(ClientMessage::Authenticate(tag)).await?;
        Ok(())
    }
}

View on GitHub (pinned to 00a735a899)