juanfont/headscale · error · ErrInvalidAuthIDPrefix

auth ID has invalid prefix

Error message

auth ID has invalid prefix

What it means

ErrInvalidAuthIDPrefix is a sentinel error in hscontrol/types/common.go:27 returned by AuthID.Validate() (common.go:68-72) when an AuthID string does not start with the required 'hskey-authreq-' prefix (wrapped with the expected prefix in the message). Any parse via AuthIDOfString of a foreign or corrupted identifier hits it.

Source

Thrown at hscontrol/types/common.go:27

	"runtime"
	"strings"
	"sync/atomic"
	"time"

	"tailscale.com/util/rands"
)

const (
	SelfUpdateIdentifier = "self-update"
	DatabasePostgres     = "postgres"
	DatabaseSqlite       = "sqlite3"
)

// Common errors.
var (
	ErrCannotParsePrefix   = errors.New("cannot parse prefix")
	ErrInvalidAuthIDLength = errors.New("auth ID has invalid length")
	ErrInvalidAuthIDPrefix = errors.New("auth ID has invalid prefix")
)

const (
	authIDPrefix       = "hskey-authreq-"
	authIDRandomLength = 24
	// AuthIDLength is the total length of an AuthID: 14 (prefix) + 24 (random).
	AuthIDLength = 38
)

type AuthID string

func NewAuthID() (AuthID, error) {
	return AuthID(authIDPrefix + rands.HexString(authIDRandomLength)), nil
}

func MustAuthID() AuthID {
	rid, err := NewAuthID()
	if err != nil {

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Verify the value starts with 'hskey-authreq-' before/instead of parsing
  2. Pass the exact auth ID issued during registration, not another identifier
  3. Use AuthIDFromString and check errors.Is(err, ErrInvalidAuthIDPrefix) to reject early
  4. Return 400 to clients sending malformed auth IDs rather than 500

Example fix

// before
if !strings.HasPrefix(s, "oidc-") { ... }

// after
if _, err := types.AuthIDFromString(s); err != nil { return http.StatusBadRequest }
Defensive patterns

Strategy: type-guard

Validate before calling

if !strings.HasPrefix(s, "hskey-authreq-") {
    return errors.New("not an auth ID")
}

Type guard

func isAuthID(s string) bool {
    return strings.HasPrefix(s, "hskey-authreq-")
}

Try / catch

if errors.Is(err, types.ErrInvalidAuthIDPrefix) { /* reject input as 400, do not retry */ }

Prevention

When it happens

Trigger: Calling types.AuthIDFromString with arbitrary strings (node keys, session IDs, other prefixes); code passing the wrong URL parameter into the auth ID parser; refactors that switch which field is treated as the auth ID.

Common situations: Mixing up identifier types in registration callbacks; fuzzing or contract tests feeding generic strings; accepting auth IDs from untrusted input without prior format checks.

Related errors


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