juanfont/headscale · error

MOCKOIDC_PORT not defined

Error message

MOCKOIDC_PORT not defined

What it means

Returned as HTTP 400 during the noise handshake when the client's declared capability version is below capver.MinSupportedCapabilityVersion; the message string comes from unsupportedClientError(version) ('unsupported client version: %s (%d)' with a human-readable Tailscale version and the numeric capver). The server also logs an 'unsupported client connected' error including node and machine keys, so you can identify which peer was rejected.

Source

Thrown at cmd/headscale/cli/mockoidc.go:23

	"encoding/json"
	"errors"
	"fmt"
	"net"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/juanfont/headscale/hscontrol/util/zlog/zf"
	"github.com/oauth2-proxy/mockoidc"
	"github.com/rs/zerolog/log"
	"github.com/spf13/cobra"
)

var (
	errMockOidcClientIDNotDefined     = errors.New("MOCKOIDC_CLIENT_ID not defined")
	errMockOidcClientSecretNotDefined = errors.New("MOCKOIDC_CLIENT_SECRET not defined")
	errMockOidcPortNotDefined         = errors.New("MOCKOIDC_PORT not defined")
	errMockOidcUsersNotDefined        = errors.New("MOCKOIDC_USERS not defined")
)

const refreshTTL = 60 * time.Minute

var accessTTL = 2 * time.Minute

func init() {
	rootCmd.AddCommand(mockOidcCmd)
}

var mockOidcCmd = &cobra.Command{
	Use:   "mockoidc",
	Short: "Runs a mock OIDC server for testing",
	Long:  "This internal command runs a OpenID Connect for testing purposes",
	RunE: func(cmd *cobra.Command, args []string) error {
		err := mockOIDC()
		if err != nil {

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Upgrade the connecting tailscale client to at least capver.TailscaleVersion(capver.MinSupportedCapabilityVersion) for your headscale build (check the log line's minimum_version field), then 'tailscale down && tailscale up'.
  2. Find the offending machine from the log's node.key/machine.key fields and target its upgrade first.
  3. If you cannot upgrade a client immediately, pin headscale to the last release whose capver floor that client meets.
  4. For custom clients, report a capability version >= the minimum in the handshake.

Example fix

# before (old client rejected with 400 unsupported client version)
$ tailscale version   # e.g. 1.32.0

# after
# Debian/Ubuntu example:
sudo apt update && sudo apt install tailscale
# or upstream:
curl -fsSL https://tailscale.com/install.sh | sh
tailscale up --login-server https://headscale.example.com
Defensive patterns

Strategy: validation

Validate before calling

// Check client capver before registering (mirrors isSupportedVersion).
clientVer := tailcfg.CurrentCapabilityVersion
if clientVer < capver.MinSupportedCapabilityVersion {
    return fmt.Errorf("client capver %d too old; need >= %d (%s)",
        clientVer, capver.MinSupportedCapabilityVersion,
        capver.TailscaleVersion(capver.MinSupportedCapabilityVersion))
}

Prevention

When it happens

Trigger: An old tailscaled (e.g. anything older than the minimum supported release, such as 1.x versions predating the floor) running 'tailscale up' against this headscale; a vendored/forked client reporting a low capability version; embedded devices shipping stale tailscale binaries.

Common situations: Upgrading headscale past a capver floor (each headscale release raises MinSupportedCapabilityVersion) while fleets still run old tailscale clients; long-lived IoT/routers never updated; OS-distro tailscale packages that lag far behind upstream.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/4cf4b5090fe93bc8. Report an issue: GitHub.