fatedier/frp · error
get addr and extra payload timeout
Error message
get addr and extra payload timeout
What it means
waitForwardAddrAndExtraPayload waits on channels fed by the tcpip-forward SSH request and the first opened channel's payload, guarded by a 3-second timer. If either the forward address request or the extra payload string has not arrived within 3 seconds, this error aborts the connection. It exists because a well-behaved frp SSH client sends both immediately after connecting.
Source
Thrown at pkg/ssh/server.go:251
go s.handleNewChannel(newChannel, extraPayloadCh)
}
}()
var (
addr *tcpipForward
extraPayload string
)
timer := time.NewTimer(timeout)
defer timer.Stop()
for {
select {
case v := <-addrCh:
addr = v
case extra := <-extraPayloadCh:
extraPayload = extra
case <-timer.C:
return nil, "", fmt.Errorf("get addr and extra payload timeout")
}
if addr != nil && extraPayload != "" {
break
}
}
return addr, extraPayload, nil
}
func (s *TunnelServer) parseClientAndProxyConfigurer(_ *tcpipForward, extraPayload string) (*v1.ClientCommonConfig, v1.ProxyConfigurer, string, error) {
helpMessage := ""
cmd := &cobra.Command{
Use: "ssh v0@{address} [command]",
Short: "ssh v0@{address} [command]",
Run: func(*cobra.Command, []string) {},
}
cmd.SetGlobalNormalizationFunc(config.WordSepNormalizeFunc)
args := strings.Split(extraPayload, " ")View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Always pass the proxy command as the ssh command argument: ssh -p port v0@host "tcp 127.0.0.1:22 --remotePort 6000".
- If automating, open the connection and write the payload in one step (paramiko: exec_command; go ssh: start the channel immediately).
- Avoid using this port with a plain interactive shell — it is a tunnel endpoint, not a login shell.
- For flaky networks, send the payload as early as possible; the 3s window is fixed and not configurable.
Example fix
# before (opens connection, sends nothing) ssh -p 7000 v0@frps-host # after (command sent immediately) ssh -p 7000 v0@frps-host "tcp 127.0.0.1:22 --remotePort 6000"
Defensive patterns
Strategy: validation
Validate before calling
# always send the command in the same step as connecting
# paramiko example
cli = paramiko.SSHClient()
cli.connect(host, port=7000, username="v0", key_filename="~/.ssh/frp_gateway")
stdin, stdout, stderr = cli.exec_command("tcp 127.0.0.1:22 --remotePort 6000", timeout=5) # payload sent immediately Prevention
- Never open a bare interactive shell to the gateway port.
- In automation, compose the command string before connecting.
- Health checks should TCP-probe, not complete SSH handshakes then idle.
When it happens
Trigger: Client connects to the frp SSH gateway but sends no command payload (plain `ssh -p port v0@host` with no command, then idles), a non-frp SSH client that only opens a session channel, network stalls that delay the first packets past 3s, or automation that opens the TCP connection and waits.
Common situations: Interactive shell into the gateway out of curiosity (the gateway is not a shell); port scanners or health checks that complete the TCP+SSH handshake but send nothing; scripts that establish the connection before composing the command; very slow or lossy links exceeding the fixed 3s budget.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- parse flags from ssh client error: %v
- invalid proxy type: %s, support types: %v
- wait proxy status ready timeout
- ps.Err
- unexpected frame type %d, want %d
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/5e18e1ed4076f156.
Report an issue: GitHub.