fatedier/frp · warning

no proxy status found

Error message

no proxy status found

What it means

Returned by Client.GetProxyStatus when /api/status parsed fine but no proxy with the requested name exists in any status group. It means the admin API is healthy but the named proxy is not registered (yet) — typically not yet started, already closed, or the name is wrong.

Source

Thrown at pkg/sdk/client/client.go:55

	if err != nil {
		return nil, err
	}
	content, err := c.do(req)
	if err != nil {
		return nil, err
	}
	allStatus := make(model.StatusResp)
	if err = json.Unmarshal([]byte(content), &allStatus); err != nil {
		return nil, fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(content))
	}
	for _, pss := range allStatus {
		for _, ps := range pss {
			if ps.Name == name {
				return &ps, nil
			}
		}
	}
	return nil, fmt.Errorf("no proxy status found")
}

func (c *Client) GetAllProxyStatus(ctx context.Context) (model.StatusResp, error) {
	req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/status", nil)
	if err != nil {
		return nil, err
	}
	content, err := c.do(req)
	if err != nil {
		return nil, err
	}
	allStatus := make(model.StatusResp)
	if err = json.Unmarshal([]byte(content), &allStatus); err != nil {
		return nil, fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(content))
	}
	return allStatus, nil
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. List all statuses with GetAllProxyStatus and compare actual names with the requested one.
  2. If polling at startup, retry with backoff until the proxy registers or a timeout expires.
  3. Check the proxy exists in frpc.toml and that its name matches exactly (names are case-sensitive).

Example fix

// before
status, err := client.GetProxyStatus(ctx, "web")
if err != nil { return err } // fails during frpc startup

// after
var status *model.ProxyStatusResp
err = retryWithBackoff(ctx, 5*time.Second, func() error {
    var e error
    status, e = client.GetProxyStatus(ctx, "web")
    return e
})
Defensive patterns

Strategy: retry

Validate before calling

// confirm the proxy name exists before targeted queries
all, err := client.GetAllProxyStatus(ctx)
if err != nil { return err }
for _, group := range all {
    for _, ps := range group {
        if ps.Name == name { /* exists */ }
    }
}

Try / catch

var st *model.ProxyStatusResp
err := backoff Retry(ctx, func() error {
    var e error
    st, e = client.GetProxyStatus(ctx, "web")
    return e // retry while proxy not yet registered
})

Prevention

When it happens

Trigger: Querying a proxy by name before frpc finished establishing it; after the proxy exited or failed to start; using a name that differs from the config (case, prefix, or renamed proxy).

Common situations: Polling loops racing against frpc startup; typos in the proxy name; querying after stop/reload removed the proxy; health checks referencing an old name after config refactor.

Related errors


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