tailscale/tailscale · error

errTaggedRemoteSource

errTaggedRemoteSource

Error message

tagged-remote-source

What it means

errTaggedRemoteSource is returned when WhoIs identifies the requesting node as tagged and it is not the node running the web client. Tagged nodes have machine identity without an owning user, so they cannot hold or create a user browser session. The web client therefore refuses them outright.

Source

Thrown at client/web/auth.go:78

	}
	return true
}

// isExpired reports true if s is expired.
// 2023-10-05: Sessions expire by default 30 days after creation.
func (s *browserSession) isExpired(now time.Time) bool {
	return !s.Created.IsZero() && now.After(s.expires())
}

// expires reports when the given session expires.
func (s *browserSession) expires() time.Time {
	return s.Created.Add(sessionCookieExpiry)
}

var (
	errNoSession          = errors.New("no-browser-session")
	errNotUsingTailscale  = errors.New("not-using-tailscale")
	errTaggedRemoteSource = errors.New("tagged-remote-source")
	errTaggedLocalSource  = errors.New("tagged-local-source")
	errNotOwner           = errors.New("not-owner")
)

// getSession retrieves the browser session associated with the request,
// if one exists.
//
// An error is returned in any of the following cases:
//
//   - (errNotUsingTailscale) The request was not made over tailscale.
//
//   - (errNoSession) The request does not have a session.
//
//   - (errTaggedRemoteSource) The source is remote (another node) and tagged.
//     Users must use their own user-owned devices to manage other nodes'
//     web clients.
//
//   - (errTaggedLocalSource) The source is local (the same node) and tagged.

View on GitHub (pinned to 6e0912f979)

Solutions

  1. Access the web client from a user-owned (untagged) device belonging to the node owner
  2. Tighten ACLs so tagged devices cannot reach the web client port (usually 5252)
  3. If the machine must be untagged, remove its tags and re-register it as a user device

Example fix

# before
acl grants tag:server -> web client port; curl from tagged node -> errTaggedRemoteSource

# after
access the UI from your laptop (user-owned node) over its tailscale IP, or remove --advertise-tags from the source machine
Defensive patterns

Strategy: try-catch

Validate before calling

// if you control the tailnet, keep tagged devices out of the web port in ACLs:
// {"action": "deny", "src": ["tag:server"], "dst": ["tag:web:5252"]}

Type guard

func isTaggedSource(err error) bool {
    return err != nil && (errors.Is(err, errTaggedRemoteSource) || errors.Is(err, errTaggedLocalSource))
}

Try / catch

if _, _, _, err := s.getSession(r); err != nil {
    switch {
    case errors.Is(err, errTaggedRemoteSource):
        http.Error(w, "tagged nodes cannot use the web client; connect from a user-owned device", http.StatusForbidden)
    case err != nil:
        // other cases
    }
}

Prevention

When it happens

Trigger: A device registered with --advertise-tags (e.g. tag:server) connects to the web client port of another node; an ACL rule grants a tagged device access to the web client's port; automation running on a tagged node points a browser or HTTP client at the web UI.

Common situations: Servers tagged for service ACLs that can also reach the web client port; reusing a tagged machine to administer another node; ACL changes that accidentally expose the web client port to tag groups.

Related errors


AI-assisted analysis of tailscale/tailscale@6e0912f979 (2026-08-18). Data as JSON: /api/errors/44cea1eddb13ab46. Report an issue: GitHub.