ekzhang/bore · error
server requires secret, but no secret was provided
Error message
server requires secret, but no secret was provided
What it means
During `Authenticator::server_handshake`, the server sent a challenge and expected the client to reply with a `ClientMessage::Authenticate(tag)`. Instead, the first message received (or an EOF/timeout) was anything else, so the server cannot authenticate the connection. This library throws it because the server was started with a secret and will not accept unauthenticated clients.
Solutions
- Start the client with the same secret as the server: `bore local <port> --to <host> --secret mysecret`.
- If the server should not require auth, restart it without `--secret`.
- Ensure client and server are the same bore version so the handshake protocol matches.
- Check that nothing between client and server (proxy, tunnel) interferes with the framed protocol messages.
Example fix
// before (server has --secret) bore local 3000 --to bore.example.com // after bore local 3000 --to bore.example.com --secret mysecret
Defensive patterns
Strategy: validation
Validate before calling
// Before connecting, confirm the server requires a secret and you have one configured
if server_requires_secret && client_secret.is_none() {
bail!("server requires --secret; provide the same secret as 'bore server --secret'");
} Try / catch
match Client::new(...).await {
Err(e) if e.to_string().contains("no secret was provided") => configure_secret_and_retry(),
other => other,
} Prevention
- Always pass --secret when the server was started with --secret.
- Deploy client and server from the same configuration source so secrets stay in sync.
- Document the secret requirement wherever the server endpoint is published.
When it happens
Trigger: Client connected to a server started with `--secret` but the client never sent `Authenticate`: the client sent `Hello` directly (no secret configured on the client), sent some other unexpected message, or the connection closed/ephemeral message arrived before authentication.
Common situations: Server run with `bore server --secret mysecret` while the client omits `--secret`; mismatched client/server versions where one side does not authenticate; a proxy or misconfigured port forwarding stripping/reordering the handshake; a non-bore client (e.g. plain TCP scanner or health check) hitting the port.
Related errors
- expected authentication challenge, but no secret was…
- server requires authentication, but no client secret was…
- server error
- unexpected initial non-hello message
- unexpected EOF
AI-assisted analysis of ekzhang/bore@00a735a899 (2026-09-08).
Data as JSON: /api/errors/3fcc59530c26cc68.
Report an issue: GitHub.
Appendix: source
Thrown at src/auth.rs:62
hmac.verify_slice(&tag).is_ok()
} else {
false
}
}
/// As the server, send a challenge to the client and validate their response.
pub async fn server_handshake<T: AsyncRead + AsyncWrite + Unpin>(
&self,
stream: &mut Delimited<T>,
) -> Result<()> {
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)