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

  1. Always pass the proxy command as the ssh command argument: ssh -p port v0@host "tcp 127.0.0.1:22 --remotePort 6000".
  2. If automating, open the connection and write the payload in one step (paramiko: exec_command; go ssh: start the channel immediately).
  3. Avoid using this port with a plain interactive shell — it is a tunnel endpoint, not a login shell.
  4. 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

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

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/5e18e1ed4076f156. Report an issue: GitHub.