gastownhall/beads · error
peer name must start with a letter and contain only alphanum
Error message
peer name must start with a letter and contain only alphanumeric characters, hyphens, and underscores
What it means
ValidatePeerName requires peer names to match ^[a-zA-Z][a-zA-Z0-9_-]*$: they must start with a letter and contain only alphanumerics, hyphens, and underscores. This guarantees the name is safe as a Dolt remote identifier (no spaces, slashes, or leading digits/symbols). Names failing the regex get this error.
Source
Thrown at internal/storage/issueops/federation.go:25
"regexp"
"strings"
"github.com/steveyegge/beads/internal/storage"
)
// validPeerNameRegex matches valid peer names (alphanumeric, hyphens, underscores).
var validPeerNameRegex = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]*$`)
// ValidatePeerName checks that a peer name is safe for use as a Dolt remote name.
func ValidatePeerName(name string) error {
if name == "" {
return fmt.Errorf("peer name cannot be empty")
}
if len(name) > 64 {
return fmt.Errorf("peer name too long (max 64 characters)")
}
if !validPeerNameRegex.MatchString(name) {
return fmt.Errorf("peer name must start with a letter and contain only alphanumeric characters, hyphens, and underscores")
}
return nil
}
// AddFederationPeerInTx upserts a federation peer record. The encryptedPwd
// should already be encrypted by the caller; pass nil for no password.
func AddFederationPeerInTx(ctx context.Context, tx *sql.Tx, peer *storage.FederationPeer, encryptedPwd []byte) error {
if err := ValidatePeerName(peer.Name); err != nil {
return fmt.Errorf("invalid peer name: %w", err)
}
_, err := tx.ExecContext(ctx, `
INSERT INTO federation_peers (name, remote_url, username, password_encrypted, sovereignty)
VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
remote_url = VALUES(remote_url),
username = VALUES(username),
password_encrypted = VALUES(password_encrypted),View on GitHub (pinned to 71377f2769)
Solutions
- Rewrite the peer name to start with a letter and use only letters, digits, hyphens, and underscores (e.g. "peer-1").
- Sanitize/normalize names in your config loader (strip invalid characters, prefix a letter if it starts with a digit).
- Call ValidatePeerName early (at config parse time) so invalid names fail before federation setup.
Example fix
// before peer := "1st office peer" // after peer := "office-peer-1" // matches ^[a-zA-Z][a-zA-Z0-9_-]*$
Defensive patterns
Strategy: validation
Validate before calling
var peerNameRe = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]*$`)
if !peerNameRe.MatchString(name) {
return fmt.Errorf("peer name %q must start with a letter and use only [a-zA-Z0-9_-]", name)
} Type guard
func validPeerName(name string) bool {
var re = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]*$`)
return re.MatchString(name)
} Try / catch
if err := ValidatePeerName(peer); err != nil {
return fmt.Errorf("peer %q: %w", peer, err)
} Prevention
- Sanitize peer names on input: replace spaces/dots/slashes with hyphens, prefix a letter if it starts with a digit.
- Never use hostnames, URLs, or paths as peer names.
- Run ValidatePeerName at config-parse time so bad names fail before federation setup.
When it happens
Trigger: Calling ValidatePeerName or AddFederationPeerInTx with names like "1st-peer" (leading digit), "my peer" (space), "org/repo" (slash), "-peer" (leading hyphen), or names with punctuation.
Common situations: Using a hostname or URL as the peer name (contains dots/slashes); human-entered names with spaces; auto-generated names starting with a digit or underscore-derived prefix.
Related errors
- peer name too long (max 64 characters)
- peer name cannot be empty
- peer name must start with a letter and contain only alphanum
- invalid peer name: %w
- peer name cannot be empty
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/80ba5d21220b6bbd.
Report an issue: GitHub.