wavetermdev/waveterm · error

error setting jwt private key: %w

Error message

error setting jwt private key: %w

What it means

After decoding, InitMainServer installs the private key into the wavejwt package via wavejwt.SetPrivateKey. This error means the decoded bytes were rejected — most commonly they are not a valid ed25519 private key (wrong length), so JWT signing cannot be initialized.

Source

Thrown at pkg/wcore/wcore.go:210

	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,
		})
		log.Printf("JWT Public Key:\n%s", string(pubKeyPem))
	}

	return nil

View on GitHub (pinned to a4447c1563)

Solutions

  1. Clear both JwtPrivateKey and JwtPublicKey so InitMainServer generates a fresh ed25519 pair
  2. Check lengths after decode: private key must be 64 bytes, public key 32 bytes; swap the fields if they were reversed
  3. Regenerate keys with wavejwt.GenerateKeyPair and store them base64(StdEncoding)-encoded
  4. Check the wrapped error message for the expected key size and compare with your stored data

Example fix

// before
mainServer.JwtPrivateKey = base64.StdEncoding.EncodeToString(pubBytes)
// after
keyPair, _ := wavejwt.GenerateKeyPair()
mainServer.JwtPrivateKey = base64.StdEncoding.EncodeToString(keyPair.PrivateKey)
Defensive patterns

Strategy: validation

Validate before calling

b, err := base64.StdEncoding.DecodeString(mainServer.JwtPrivateKey)
if err != nil || len(b) != ed25519.PrivateKeySize {
    mainServer.JwtPrivateKey = "" // force regeneration
}

Type guard

func isEd25519PrivateKey(b []byte) bool { return len(b) == ed25519.PrivateKeySize }

Try / catch

if err := wcore.InitMainServer(); err != nil {
    if strings.Contains(err.Error(), "setting jwt private key") {
        regenerateJwtKeys() // wavejwt.GenerateKeyPair + store
        return wcore.InitMainServer()
    }
    panic(err)
}

Prevention

When it happens

Trigger: wavejwt.SetPrivateKey(privateKeyBytes) returns an error because privateKeyBytes is not ed25519.PrivateKeySize (64) bytes — the stored value decodes but holds a public key, a truncated key, or bytes from a different algorithm.

Common situations: Swapped public/private fields in the DB; keys from an older/other key scheme; manually regenerated keys of the wrong size; partial corruption.

Related errors


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