wavetermdev/waveterm · error
error decoding jwt private key: %w
Error message
error decoding jwt private key: %w
What it means
InitMainServer decodes MainServer.JwtPrivateKey from base64 (StdEncoding) before installing it into wavejwt. This error means the stored private key string is not valid standard base64, so startup aborts. It indicates the stored key data is corrupt or was written in a non-standard encoding.
Source
Thrown at pkg/wcore/wcore.go:201
keyPair, err := wavejwt.GenerateKeyPair()
if err != nil {
return fmt.Errorf("error generating jwt keypair: %w", err)
}
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)View on GitHub (pinned to a4447c1563)
Solutions
- Delete the stored MainServer singleton (or wave.db) so InitMainServer regenerates a fresh key pair on next start
- Verify the field is valid standard base64: `base64.StdEncoding.DecodeString(key)` in a scratch program; re-encode with StdEncoding if it was URL-safe
- Strip whitespace/newlines from the stored value if present
- Do not hand-edit the DB; instead clear the Jwt* fields to empty so they are regenerated
Example fix
// before: key stored URL-safe key = base64.URLEncoding.EncodeToString(priv) // after: must be StdEncoding for this code path key = base64.StdEncoding.EncodeToString(priv)
Defensive patterns
Strategy: validation
Validate before calling
if _, err := base64.StdEncoding.DecodeString(mainServer.JwtPrivateKey); err != nil {
mainServer.JwtPrivateKey = "" // force regeneration path
} Type guard
func isValidB64Key(s string, size int) bool {
b, err := base64.StdEncoding.DecodeString(s)
return err == nil && len(b) == size
} Try / catch
if err := wcore.InitMainServer(); err != nil {
if strings.Contains(err.Error(), "decoding jwt private key") {
clearJwtKeysInDB() // blank fields; restart regenerates
return wcore.InitMainServer()
}
panic(err)
} Prevention
- Never hand-edit wave.db key fields
- Always encode keys with base64.StdEncoding
- After decode, assert ed25519.PrivateKeySize (64) bytes
- Back up the DB before upgrades/migrations
When it happens
Trigger: base64.StdEncoding.DecodeString(mainServer.JwtPrivateKey) fails because the DB field contains a non-base64 string — manual DB edits, truncation, whitespace/newlines (URL-safe or raw encoding instead of StdEncoding), or corruption from an interrupted write.
Common situations: Hand-editing wave.db; copying key values between environments with encoding changes; restoring a partially-written DB from backup; migration from a version that stored raw (non-base64) bytes.
Related errors
- error decoding jwt public key: %w
- error decoding jwt public key: %v
- no data available for base64 extraction
- error getting jwt public key: %v
- error setting jwt public key: %v
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/4c6bc3309a58e2d8.
Report an issue: GitHub.