Tencent/WeKnora · error

missing external user id header

Error message

missing external user id header

What it means

errMissingDirectHeader is returned by resolveAPIPrincipal when the API auth mode requires the X-External-User-ID header (cfg.RequireDirectHeader) but the request does not carry it. It is a sentinel guard on incoming request headers, converted by apiPrincipalAuthErrorMessage to an 'Unauthorized: missing external user id header' response.

Source

Thrown at internal/middleware/auth.go:30

	"time"

	"github.com/Tencent/WeKnora/internal/config"
	"github.com/Tencent/WeKnora/internal/logger"
	"github.com/Tencent/WeKnora/internal/types"
	"github.com/Tencent/WeKnora/internal/types/interfaces"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
)

const (
	defaultExternalUserIDHeader    = "X-External-User-ID"
	defaultExternalUserTokenHeader = "X-External-User-Token"
	maxExternalUserIDLen           = 128
	maxExternalUserTokenTTL        = 24 * time.Hour
)

var (
	errMissingDirectHeader      = errors.New("missing external user id header")
	errInvalidExternalUserID    = errors.New("invalid external user id")
	errInvalidExternalUserToken = errors.New("invalid external user token")
)

// 无需认证的API列表
var noAuthAPI = map[string][]string{
	"/health":                 {"GET"},
	"/api/v1/auth/register":   {"POST"},
	"/api/v1/auth/login":      {"POST"},
	"/api/v1/auth/auto-setup": {"POST"},
	// Share-link surfaces accept a plaintext invite token from anonymous
	// callers (an invitee who hasn't registered yet). They are registered
	// as public routes in RegisterAuthRoutes and rate-limited by IP, so the
	// global Auth middleware must let them through — otherwise opening a
	// share link while logged out 401s and the frontend bounces the user to
	// /login instead of the register page (issue #1617).
	"/api/v1/auth/invitations/lookup": {"POST"},
	"/api/v1/auth/register-by-invite": {"POST"},

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Client must send the X-External-User-ID header on API requests
  2. If the header is optional, disable RequireDirectHeader in config so the fallback principal is used
  3. Check proxy/gateway config is not stripping the custom header
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at internal/middleware/auth.go:30 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/7e38dddc3af8df79. Report an issue: GitHub.