wavetermdev/waveterm · error
bad response from server: questions has len %d, echos has le
Error message
bad response from server: questions has len %d, echos has len %d
What it means
The keyboard-interactive auth callback validates that the server sent equal-length 'questions' and 'echos' arrays before prompting the user. A mismatch means the server produced a malformed keyboard-interactive challenge, so the client cannot map answers back to prompts and aborts with this error. It protects against misbehaving or non-standard SSH servers.
Source
Thrown at pkg/remote/sshclient.go:431
if err != nil {
blocklogger.Infof(connCtx, "[conndebug] ERROR Password Authentication failed: %v\n", SimpleMessageFromPossibleConnectionError(err))
return "", ConnectionError{ConnectionDebugInfo: debugInfo, Err: err}
}
blocklogger.Infof(connCtx, "[conndebug] got password from user, sending to ssh\n")
return response.Text, nil
}
}
func createInteractiveKbdInteractiveChallenge(connCtx context.Context, remoteName string, debugInfo *ConnectionDebugInfo) func(name, instruction string, questions []string, echos []bool) (answers []string, err error) {
return func(name, instruction string, questions []string, echos []bool) (answers []string, outErr error) {
defer func() {
panicErr := panichandler.PanicHandler("sshclient:kbdinteractive-callback", recover())
if panicErr != nil {
outErr = panicErr
}
}()
if len(questions) != len(echos) {
return nil, fmt.Errorf("bad response from server: questions has len %d, echos has len %d", len(questions), len(echos))
}
for i, question := range questions {
echo := echos[i]
answer, err := promptChallengeQuestion(connCtx, question, echo, remoteName)
if err != nil {
return nil, ConnectionError{ConnectionDebugInfo: debugInfo, Err: utilds.MakeCodedError(ConnErrCode_UserCancelled, err)}
}
answers = append(answers, answer)
}
return answers, nil
}
}
func promptChallengeQuestion(connCtx context.Context, question string, echo bool, remoteName string) (answer string, err error) {
// limited to 15 seconds for some reason. this should be investigated more
// in the future
ctx, cancelFn := context.WithTimeout(connCtx, 60*time.Second)
defer cancelFn()View on GitHub (pinned to a4447c1563)
Solutions
- Update the SSH server / appliance firmware to a version with correct keyboard-interactive support.
- Disable keyboard-interactive auth on the server (PasswordAuthentication or pubkey-only) so a compliant method is used.
- Connect directly to the host if the malformed challenge comes from an intermediate jump/bastion device.
- If you control the PAM config, fix or replace the MFA module returning mismatched prompts.
Example fix
// before (sshd_config on server) KbdInteractiveAuthentication yes // after KbdInteractiveAuthentication no # or fix the PAM module emitting mismatched prompts
Defensive patterns
Strategy: retry
Validate before calling
// probe the server before connecting
conn, err := ssh.Dial("tcp", host, ssh.ClientConfig{...})
// if you get this error deterministically, the server's kbd-interactive is broken Try / catch
if err != nil {
if strings.Contains(err.Error(), "bad response from server") {
// retry with a ClientConfig that disables KeyboardInteractiveChallenge,
// relying on password/publickey auth
}
} Prevention
- Test connectivity with OpenSSH's ssh client first; if it also fails, the server is at fault.
- Keep SSH server/appliance firmware updated.
- Prefer publickey auth on servers with non-standard PAM/MFA stacks.
- Disable kbd-interactive on the server if it emits mismatched prompts.
When it happens
Trigger: Connecting to an SSH server (or intermediate gateway/MFA device) whose keyboard-interactive implementation returns challenges where len(questions) != len(echos), e.g. a buggy PAM stack or custom SSH server.
Common situations: Connecting through VPN/MFA gateways, multi-factor PAM modules, or non-OpenSSH servers (some appliances, older firmware) that emit inconsistent kbd-interactive packets.
Related errors
- cannot parse connection name: %w
- getting ssh connection status: %w
- connecting connection: %w
- --conn parameter is required
- cannot start shellproc: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/1a8032033541bb44.
Report an issue: GitHub.