wavetermdev/waveterm · critical
error updating mainserver: %w
Error message
error updating mainserver: %w
What it means
After generating new JWT keys (or otherwise marking the MainServer singleton dirty), InitMainServer persists it with wstore.DBUpdate. This error wraps a failed update, meaning the newly generated keys could not be saved to the database.
Source
Thrown at pkg/wcore/wcore.go:195
} else if err != nil {
return fmt.Errorf("error getting mainserver: %w", err)
}
needsUpdate := false
if mainServer.JwtPrivateKey == "" || mainServer.JwtPublicKey == "" {
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 {View on GitHub (pinned to a4447c1563)
Solutions
- Free disk space / fix quota, and ensure the DB directory is writable
- Check the wrapped cause for 'database is locked' and close other Wave instances
- Verify the filesystem is not mounted read-only (especially in containers)
- If the DB is corrupt, back up and remove wave.db so a fresh DB and keys are created
Example fix
// before (container) volumes: ["./wave:/root/.waveterm:ro"] // after volumes: ["./wave:/root/.waveterm:rw"]
Defensive patterns
Strategy: validation
Validate before calling
// before startup: verify DB is writable
f, err := os.OpenFile(dbPath, os.O_RDWR, 0o600)
if err != nil {
log.Fatalf("wave.db not writable: %v", err)
}
f.Close() Try / catch
if err := wcore.InitMainServer(); err != nil {
if strings.Contains(err.Error(), "readonly") || strings.Contains(err.Error(), "locked") {
log.Fatalf("fix db mount/locks before retrying: %v", err)
}
panic(err)
} Prevention
- Mount the config/db directory read-write in containers
- Keep free disk space above a minimum threshold
- Run a single app instance per database file
- Avoid killing the process mid-write to prevent corruption
When it happens
Trigger: wstore.DBUpdate(ctx, mainServer) returns an error during InitMainServer — SQLite write failure (disk full, read-only filesystem, DB lock held by another process, corruption), or the 5-second context deadline expiring mid-write.
Common situations: Disk quota/full disk on first run; ~/.waveterm on a read-only mount; concurrent Wave processes locking the DB; crash-damaged database.
Related errors
- error updating client data: %w
- error updating object: %w
- error updating client: %w
- error inserting client: %w
- error inserting mainserver: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/2d72cfb5e5313155.
Report an issue: GitHub.