{"record":{"id":"dcc20e36f05f893f","repo":"gastownhall/beads","slug":"peer-name-must-start-with-a-letter-and-contain-onl","errorCode":null,"errorMessage":"peer name must start with a letter and contain only alphanumeric characters, hyphens, and underscores","messagePattern":"peer name must start with a letter and contain only alphanumeric characters, hyphens, and underscores","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/credentials.go","lineNumber":48,"sourceCode":"const awsResponseChecksumValidationEnv = \"AWS_RESPONSE_CHECKSUM_VALIDATION\"\n\n// federationEnvMutex protects process-wide env vars from concurrent access.\n// Environment variables are process-global, so we need to serialize federation operations.\nvar federationEnvMutex sync.Mutex\n\n// validPeerNameRegex matches valid peer names (alphanumeric, hyphens, underscores)\nvar validPeerNameRegex = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]*$`)\n\n// validatePeerName checks that a peer name is safe for use as a Dolt remote name\nfunc validatePeerName(name string) error {\n\tif name == \"\" {\n\t\treturn fmt.Errorf(\"peer name cannot be empty\")\n\t}\n\tif len(name) > 64 {\n\t\treturn fmt.Errorf(\"peer name too long (max 64 characters)\")\n\t}\n\tif !validPeerNameRegex.MatchString(name) {\n\t\treturn fmt.Errorf(\"peer name must start with a letter and contain only alphanumeric characters, hyphens, and underscores\")\n\t}\n\treturn nil\n}\n\n// initCredentialKey loads or generates the credential encryption key.\n// The key file is stored in .beads/ (beadsDir), NOT in .beads/dolt/ (dbPath),\n// to avoid creating ghost directories in shared-server mode (GH bd-cby).\n// Falls back to the old dbPath location for transparent migration.\nfunc (s *DoltStore) initCredentialKey(ctx context.Context) error {\n\tif s.beadsDir == \"\" {\n\t\treturn nil // No filesystem path — credential encryption unavailable\n\t}\n\n\tkeyPath := filepath.Join(s.beadsDir, credentialKeyFile)\n\n\t// Try to load from new location (.beads/)\n\tkey, err := os.ReadFile(keyPath) //nolint:gosec // G304: keyPath is derived from trusted beadsDir, not user input\n\tif err == nil && len(key) == 32 {","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/credentials.go#L30-L66","documentation":"validatePeerName enforces ^[a-zA-Z][a-zA-Z0-9_-]*$ so the name is safe as a Dolt remote name (no slashes, dots, spaces, or leading digits/symbols). Names violating this pattern are rejected before remote/credential creation.","triggerScenarios":"addFederationPeer is given a name that starts with a digit/symbol or contains disallowed characters — e.g. `1st-peer`, `my peer`, `org/repo`, `peer.local`, or a URL used as the name.","commonSituations":"Using hostnames with dots, org/repo slashes, or names auto-derived from URLs; leading-digit numbering schemes (`01-remote`); spaces from unquoted shell arguments.","solutions":["Rename the peer to start with a letter and use only alphanumerics, hyphens, and underscores: `remote01`, `backup-remote`, `upstream_main`","Sanitize generated names in scripts: replace invalid characters with `-` and prefix a letter if it starts with a digit","Quote shell arguments to avoid spaces splitting the name into separate args"],"exampleFix":"// before\nbd peer add 01_backup.remote   # invalid characters\n// after\nbd peer add r01-backup-remote","handlingStrategy":"validation","validationCode":"var peerNameRe = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]*$`)\nfunc sanitizePeerName(name string) string {\n    name = strings.Map(func(r rune) rune {\n        if (r>='a'&&r<='z')||(r>='A'&&r<='Z')||(r>='0'&&r<='9')||r=='-'||r=='_' { return r }\n        return '-'\n    }, strings.ReplaceAll(name, \" \", \"-\"))\n    if name != \"\" && name[0] >= '0' && name[0] <= '9' { name = \"p\" + name }\n    return name\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Start peer names with a letter; prefix numeric identifiers (e.g. `p01-remote`)","Replace dots, slashes, and spaces with hyphens or underscores in generated names","Quote shell arguments to prevent spaces from splitting the name","Test derived names against ^[a-zA-Z][a-zA-Z0-9_-]*$ before use"],"tags":["validation","federation","peer-name","regex"],"backgroundTag":"invalid-peer-name","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}