ginuerzh/gost · error
status %d
Error message
status %d
What it means
In the gost relay client path, relayConn.Read (relay.go:288) reads the server's relay response header once and, if the returned status is not relay.StatusOK (0), surfaces "status %d" with the numeric status code. It means the relay server accepted the connection but rejected the tunnel request instead of establishing the data channel.
Source
Thrown at relay.go:289
headerSent bool
}
func (c *relayConn) Read(b []byte) (n int, err error) {
c.once.Do(func() {
if c.isServer {
return
}
resp := new(relay.Response)
_, err = resp.ReadFrom(c.Conn)
if err != nil {
return
}
if resp.Version != relay.Version1 {
err = relay.ErrBadVersion
return
}
if resp.Status != relay.StatusOK {
err = fmt.Errorf("status %d", resp.Status)
return
}
})
if err != nil {
log.Logf("[relay] %s <- %s: %s", c.Conn.LocalAddr(), c.Conn.RemoteAddr(), err)
return
}
if !c.udp {
return c.Conn.Read(b)
}
var bb [2]byte
_, err = io.ReadFull(c.Conn, bb[:])
if err != nil {
return
}
dlen := int(binary.BigEndian.Uint16(bb[:]))View on GitHub (pinned to a33fdbf4c9)
Solutions
- Check the numeric status in the message against the relay protocol status codes to identify the exact rejection (e.g. unauthorized vs forbidden)
- Verify relay node credentials (user/password) in the gost config match the upstream relay server's auth config
- Confirm the upstream address is actually a gost relay endpoint speaking relay protocol Version1, not an HTTP/SOCKS server
- Inspect the remote relay server logs for the corresponding rejection reason and update the local node config accordingly
Example fix
// before nodes = relay://user:wrongpass@relay.example.com:8421 // after nodes = relay://user:correctpass@relay.example.com:8421
Defensive patterns
Strategy: try-catch
Validate before calling
// before dialing, verify the relay node has credentials that match the server
if node.Auth == nil {
return errors.New("relay node requires auth credentials matching the server")
} Type guard
func isRelayStatusError(err error) bool {
return err != nil && strings.HasPrefix(err.Error(), "status ")
} Try / catch
conn, err := client.Dial(addr)
if err != nil {
if isRelayStatusError(err) {
code := strings.TrimPrefix(err.Error(), "status ")
log.Printf("relay server rejected request with status %s; check auth/config", code)
return err // server-side rejection, not transient — don't retry blindly
}
return retry(err)
} Prevention
- Match relay node user/password exactly with the upstream relay server's auth config
- Ensure the upstream address is a gost relay (Version1) endpoint, not HTTP/SOCKS
- Keep gost versions compatible on both ends to avoid status/version rejections
- Log the numeric status code from the error message and map it to the relay protocol status table
When it happens
Trigger: Connecting through a gost relay node whose server replies with a non-zero relay response status — e.g. authentication rejected by the remote relay, the remote node refusing the forward request, or a mismatch where the peer answers with an error status.
Common situations: Chained gost proxies where the upstream relay requires different credentials, the upstream address is served by a non-relay service, or relay protocol incompatibilities (the sibling ErrBadVersion check is at relay.go:284).
Related errors
AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02).
Data as JSON: /api/errors/07d6903c22a69313.
Report an issue: GitHub.