gastownhall/beads · error
invalid peer name: %w
Error message
invalid peer name: %w
What it means
addFederationPeer validates the peer name before storing credentials; this wraps any validatePeerName failure. A valid peer name must be non-empty, at most 64 characters, start with a letter, and contain only alphanumerics, hyphens, and underscores (regex ^[a-zA-Z][a-zA-Z0-9_-]*$). The name is later used as a Dolt remote name, so unsafe characters are rejected up front.
Source
Thrown at internal/storage/dolt/credentials.go:275
s.mu.RUnlock()
if key == nil {
return "", fmt.Errorf("credential encryption key not initialized")
}
return decryptWithKey(encrypted, key)
}
// AddFederationPeer adds or updates a federation peer with credentials.
// This stores credentials in the database and also adds the Dolt remote.
func (s *DoltStore) AddFederationPeer(ctx context.Context, peer *storage.FederationPeer) error {
return s.withCircuitWrite(ctx, func(ctx context.Context) error {
return s.addFederationPeer(ctx, peer)
})
}
func (s *DoltStore) addFederationPeer(ctx context.Context, peer *storage.FederationPeer) error {
// Validate peer name
if err := validatePeerName(peer.Name); err != nil {
return fmt.Errorf("invalid peer name: %w", err)
}
// Encrypt password before storing
var encryptedPwd []byte
var err error
if peer.Password != "" {
if err := s.ensureCredentialKey(ctx); err != nil {
return fmt.Errorf("failed to initialize credential key: %w", err)
}
encryptedPwd, err = s.encryptPassword(peer.Password)
if err != nil {
return fmt.Errorf("failed to encrypt password: %w", err)
}
}
// Upsert the peer credentials
_, err = s.execContext(ctx, `
INSERT INTO federation_peers (name, remote_url, username, password_encrypted, sovereignty)View on GitHub (pinned to 71377f2769)
Solutions
- Fix the peer name to match ^[a-zA-Z][a-zA-Z0-9_-]*$ (max 64 chars, starts with a letter).
- Sanitize derived names: replace '.', '/', ':' etc. with '-' and strip leading non-letters before calling AddFederationPeer.
- Call validatePeerName-equivalent checks (regex) in your own config loading to fail early with a clear message.
Example fix
// before peer.Name = "team.example.com" _ = store.AddFederationPeer(ctx, peer) // after peer.Name = "team-example-com" _ = store.AddFederationPeer(ctx, peer)
Defensive patterns
Strategy: validation
Validate before calling
var peerNameRe = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]*$`)
if peer.Name == "" || len(peer.Name) > 64 || !peerNameRe.MatchString(peer.Name) {
return fmt.Errorf("peer name %q is invalid", peer.Name)
} Try / catch
if err := store.AddFederationPeer(ctx, peer); err != nil && strings.HasPrefix(err.Error(), "invalid peer name") {
return fmt.Errorf("fix peer name %q: %w", peer.Name, err)
} Prevention
- Sanitize hostnames/URLs into remote-safe names before storing
- Validate names at config-load time, not just at write time
- Keep names short (<=64 chars) and alphanumeric
When it happens
Trigger: Calling AddFederationPeer with a peer.Name that is empty, longer than 64 chars, starts with a digit/underscore/hyphen, or contains spaces, dots, slashes, or other special characters.
Common situations: Deriving peer names from hostnames or URLs containing dots/slashes (e.g. "team.example.com", "org/repo"); user-supplied names from config files or CLI flags without pre-validation; accidentally passing an empty struct.
Related errors
- peer name too long (max 64 characters)
- peer name must start with a letter and contain only alphanum
- invalid peer name: %w
- no store is open for this workspace
- not found
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/bb86e35dbf978025.
Report an issue: GitHub.