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

  1. Free disk space / fix quota, and ensure the DB directory is writable
  2. Check the wrapped cause for 'database is locked' and close other Wave instances
  3. Verify the filesystem is not mounted read-only (especially in containers)
  4. 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

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


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