wavetermdev/waveterm · error

x-authkey header is invalid

Error message

x-authkey header is invalid

What it means

ValidateIncomingRequest authenticates incoming internal HTTP/WebSocket requests by comparing the x-authkey request header against the in-memory authkey set at startup. If the header value is present but does not match GetAuthKey(), the request is rejected with this error. This protects Wave's internal RPC endpoints from unauthorized local access.

Source

Thrown at pkg/authkey/authkey.go:23

import (
	"fmt"
	"net/http"
	"os"
)

var authkey string

const WaveAuthKeyEnv = "WAVETERM_AUTH_KEY"
const AuthKeyHeader = "X-AuthKey"

func ValidateIncomingRequest(r *http.Request) error {
	reqAuthKey := r.Header.Get(AuthKeyHeader)
	if reqAuthKey == "" {
		return fmt.Errorf("no x-authkey header")
	}
	if reqAuthKey != GetAuthKey() {
		return fmt.Errorf("x-authkey header is invalid")
	}
	return nil
}

func SetAuthKeyFromEnv() error {
	authkey = os.Getenv(WaveAuthKeyEnv)
	if authkey == "" {
		return fmt.Errorf("no auth key found in environment variables")
	}
	os.Unsetenv(WaveAuthKeyEnv)
	return nil
}

func GetAuthKey() string {
	return authkey
}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Set the same WAVE_AUTHKEY environment variable for both the server process and the client making the request, then restart both
  2. Verify the server actually accepted the key (SetAuthKeyFromEnv succeeded) and re-read it via GetAuthKey()
  3. Kill duplicate Wave server instances that may be listening with an old key
  4. If the header is set by tooling (proxy, curl script), update the injected header value to match the current key

Example fix

// before
curl -H 'x-authkey: oldkey' http://localhost:2665/awldollar
// after
export WAVE_AUTHKEY=currentkey
curl -H "x-authkey: $WAVE_AUTHKEY" http://localhost:2665/awldollar
Defensive patterns

Strategy: validation

Validate before calling

func hasValidAuthKey(r *http.Request, expected string) bool {
    return r.Header.Get("x-authkey") != "" && r.Header.Get("x-authkey") == expected
}

Type guard

func hasAuthHeader(r *http.Request) bool { return r.Header.Get("x-authkey") != "" }

Try / catch

if err := authkey.ValidateIncomingRequest(req); err != nil {
    if strings.Contains(err.Error(), "invalid") { /* key mismatch: refresh key and retry once */ }
    return err
}

Prevention

When it happens

Trigger: Any HTTP/WS request (HandleWsInternal or anonymous handler) whose x-authkey header holds a stale, wrong, or mismatched value relative to WAVE_AUTHKEY set for the running server process.

Common situations: A client (wsh, extension, older frontend) launched with a different WAVE_AUTHKEY value than the server; multiple Wave instances running with different keys; a hardcoded or cached key after the server restarted and picked up a new key.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/cdc585405f03f388. Report an issue: GitHub.