netbirdio/netbird · error

expose: %w

Error message

expose: %w

What it means

Returned by Client.Expose when the expose manager's Expose call fails. This is the management-driven reverse proxy feature: the manager talks to the management server to register the exposed service and obtain a public URL, so failures are registration/protocol/network level: management rejected the request, feature unavailable for the account, connectivity loss, or context cancellation.

Source

Thrown at client/embed/embed.go:438

	}
}

// Expose exposes a local service via the NetBird reverse proxy, making it accessible through a public URL.
// It returns an ExposeSession. Call Wait on the session to keep it alive.
func (c *Client) Expose(ctx context.Context, req ExposeRequest) (*ExposeSession, error) {
	engine, err := c.getEngine()
	if err != nil {
		return nil, err
	}

	mgr := engine.GetExposeManager()
	if mgr == nil {
		return nil, fmt.Errorf("expose manager not available")
	}

	resp, err := mgr.Expose(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("expose: %w", err)
	}

	return &ExposeSession{
		Domain:      resp.Domain,
		ServiceName: resp.ServiceName,
		ServiceURL:  resp.ServiceURL,
		mgr:         mgr,
	}, nil
}

// IdentityForIP looks up a remote peer by its tunnel IP using the
// embedded client's status recorder. Returns the peer's WireGuard public
// key and FQDN. ok=false means the IP doesn't belong to an active peer
// — offline roster peers are treated as unknown, same as foreign IPs.
func (c *Client) IdentityForIP(ip netip.Addr) (pubKey, fqdn string, ok bool) {
	if !ip.IsValid() || c.recorder == nil {
		return "", "", false
	}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Unwrap the error to distinguish transport failures (retry) from management rejections (fix request/plan).
  2. Ensure the ExposeRequest values (ports, names) are valid and the management server supports the expose feature.
  3. Retry with backoff on transient connectivity loss; use a context without an aggressive deadline.
  4. Verify the client is still connected (Status) before exposing.
Defensive patterns

Strategy: retry

Try / catch

sess, err := client.Expose(ctx, req)
if err != nil {
    if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) || isTransientNet(err) {
        // backoff and retry with a fresh context
    } else {
        // management rejected: fix request or account feature, do not retry
    }
}

Prevention

When it happens

Trigger: Expose with a context that is cancelled/deadline exceeded; management server unreachable or returning an error for the expose request; expose feature not enabled on the NetBird account/plan; malformed ExposeRequest fields (e.g. invalid port or name) rejected server-side.

Common situations: Trying expose on a self-hosted management without the reverse proxy feature configured; expired auth session between the client and management; network partitions between the embedder and management at expose time.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/c65ff2a66e85a5e3. Report an issue: GitHub.