gastownhall/beads · error
failed to decrypt password: %w
Error message
failed to decrypt password: %w
What it means
GetFederationPeer loads a federation peer row from the federation_peers table and decrypts its stored password with the store's AES-256-GCM credential key. This error is returned when decryptPassword fails, meaning the ciphertext in password_encrypted cannot be authenticated/decrypted with the currently loaded key. The library throws it to prevent silently using a corrupted or wrong-key password for peer sync.
Source
Thrown at internal/storage/dolt/credentials.go:356
if err != nil {
return nil, fmt.Errorf("failed to get federation peer: %w", err)
}
if username.Valid {
peer.Username = username.String
}
if lastSync.Valid {
peer.LastSync = &lastSync.Time
}
// Decrypt password
if len(encryptedPwd) > 0 {
if err := s.ensureCredentialKey(ctx); err != nil {
return nil, fmt.Errorf("failed to initialize credential key: %w", err)
}
peer.Password, err = s.decryptPassword(encryptedPwd)
if err != nil {
return nil, fmt.Errorf("failed to decrypt password: %w", err)
}
}
return &peer, nil
}
// ListFederationPeers returns all configured federation peers.
func (s *DoltStore) ListFederationPeers(ctx context.Context) ([]*storage.FederationPeer, error) {
rows, err := s.queryContext(ctx, `
SELECT name, remote_url, username, password_encrypted, sovereignty, last_sync, created_at, updated_at
FROM federation_peers ORDER BY name
`)
if err != nil {
return nil, fmt.Errorf("failed to list federation peers: %w", err)
}
defer rows.Close()
var peers []*storage.FederationPeerView on GitHub (pinned to 71377f2769)
Solutions
- Regenerate the peer's credentials: delete the peer (bd's peer-remove path) and re-add it with AddFederationPeer so the password is re-encrypted with the current key.
- Check that .beads/.beads-credential-key exists, is 32 bytes, and matches the one used when the peer was added; restore the original key file from backup if available.
- Verify the ciphertext is intact (not truncated by a bad import/restore); re-import the peer row if corrupted.
- If the key cannot be recovered, remove all stored peer passwords and re-enter them.
Example fix
// before: peer rows hold ciphertext from an old/lost key peer.Password, err = s.decryptPassword(encryptedPwd) // cipher: message authentication failed // after: re-add the peer so the password is re-encrypted with the current key _ = store.RemoveFederationPeer(ctx, "peer-name") peer.Password = "correct-password" err = store.AddFederationPeer(ctx, peer)
Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(filepath.Join(beadsDir, ".beads-credential-key")); err != nil {
return fmt.Errorf("credential key missing; re-add peer passwords before syncing: %w", err)
} Type guard
func isDecryptFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to decrypt password")
} Try / catch
peer, err := store.GetFederationPeer(ctx, name)
if isDecryptFailure(err) {
// re-add peer credentials to re-encrypt with current key
_ = store.RemoveFederationPeer(ctx, name)
err = store.AddFederationPeer(ctx, &storage.FederationPeer{Name: name, RemoteURL: url, Password: pwd})
} Prevention
- Back up .beads/.beads-credential-key together with the database, never separately
- When copying a workspace between machines, copy the whole .beads directory
- After restoring from backup, re-add peer passwords instead of assuming old ciphertext still decrypts
- Don't regenerate or delete the key file during key-maintenance operations
When it happens
Trigger: The peer row's password_encrypted was written with a different key than the one now in .beads/.beads-credential-key — e.g. the key file was deleted/regenerated, the workspace was copied without the key file, the DB was restored from backup while the key file is newer, or the ciphertext itself is truncated/corrupt (fails the GCM auth check, 'cipher: message authentication failed').
Common situations: Cloning or restoring .beads/dolt data from backup while keeping or regenerating the key file; syncing a workspace between machines without copying .beads-credential-key; manually editing or migrating the federation_peers table; a crash during key migration leaving stale ciphertext.
Related errors
- failed to encrypt password: %w
- failed to re-encrypt password for peer %s: %w
- failed to initialize credential key: %w
- failed to get peer credentials: %w
- no store available
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/139c7e297a2965e0.
Report an issue: GitHub.