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

  1. Rewrite the peer name to start with a letter and use only letters, digits, hyphens, and underscores (e.g. "peer-1").
  2. Sanitize/normalize names in your config loader (strip invalid characters, prefix a letter if it starts with a digit).
  3. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/80ba5d21220b6bbd. Report an issue: GitHub.