wavetermdev/waveterm · error

error decoding jwt public key: %w

Error message

error decoding jwt public key: %w

What it means

Identical to the private-key case but for MainServer.JwtPublicKey: InitMainServer base64-decodes the stored public key and wraps any DecodeString failure. A non-standard-base64 or corrupt public key aborts startup.

Source

Thrown at pkg/wcore/wcore.go:205

		mainServer.JwtPrivateKey = base64.StdEncoding.EncodeToString(keyPair.PrivateKey)
		mainServer.JwtPublicKey = base64.StdEncoding.EncodeToString(keyPair.PublicKey)
		needsUpdate = true
	}

	if needsUpdate {
		err = wstore.DBUpdate(ctx, mainServer)
		if err != nil {
			return fmt.Errorf("error updating mainserver: %w", err)
		}
	}

	privateKeyBytes, err := base64.StdEncoding.DecodeString(mainServer.JwtPrivateKey)
	if err != nil {
		return fmt.Errorf("error decoding jwt private key: %w", err)
	}
	publicKeyBytes, err := base64.StdEncoding.DecodeString(mainServer.JwtPublicKey)
	if err != nil {
		return fmt.Errorf("error decoding jwt public key: %w", err)
	}

	err = wavejwt.SetPrivateKey(privateKeyBytes)
	if err != nil {
		return fmt.Errorf("error setting jwt private key: %w", err)
	}
	err = wavejwt.SetPublicKey(publicKeyBytes)
	if err != nil {
		return fmt.Errorf("error setting jwt public key: %w", err)
	}

	pubKeyDer, err := x509.MarshalPKIXPublicKey(ed25519.PublicKey(publicKeyBytes))
	if err != nil {
		log.Printf("warning: could not marshal public key for logging: %v", err)
	} else {
		pubKeyPem := pem.EncodeToMemory(&pem.Block{
			Type:  "PUBLIC KEY",
			Bytes: pubKeyDer,

View on GitHub (pinned to a4447c1563)

Solutions

  1. Clear the Jwt* fields (or delete the singleton/DB) so a fresh key pair is generated on next start
  2. Re-encode the public key with base64.StdEncoding and store it back
  3. Check for and remove newlines/whitespace in the stored value
  4. Validate the decoded length: an ed25519 public key must decode to exactly 32 bytes

Example fix

// sanity check before restart
b, err := base64.StdEncoding.DecodeString(mainServer.JwtPublicKey)
if err != nil || len(b) != ed25519.PublicKeySize {
    mainServer.JwtPublicKey = "" // force regeneration
}
Defensive patterns

Strategy: validation

Validate before calling

if _, err := base64.StdEncoding.DecodeString(mainServer.JwtPublicKey); err != nil {
    mainServer.JwtPublicKey = "" // force regeneration path
}

Type guard

func isValidEd25519PubB64(s string) bool {
    b, err := base64.StdEncoding.DecodeString(s)
    return err == nil && len(b) == ed25519.PublicKeySize
}

Try / catch

if err := wcore.InitMainServer(); err != nil {
    if strings.Contains(err.Error(), "decoding jwt public key") {
        clearJwtKeysInDB()
        return wcore.InitMainServer()
    }
    panic(err)
}

Prevention

When it happens

Trigger: base64.StdEncoding.DecodeString(mainServer.JwtPublicKey) returns an error — the DB value is not valid standard base64 (wrong encoding variant, truncation, whitespace, manual edit, or interrupted write).

Common situations: Hand-edited or copy-pasted key values; restoring a truncated DB backup; version differences in how keys were serialized.

Related errors


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