{"record":{"id":"6dd038edff375dc4","repo":"gastownhall/beads","slug":"peer-name-cannot-be-empty-6dd038","errorCode":null,"errorMessage":"peer name cannot be empty","messagePattern":"peer name cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/federation.go","lineNumber":19,"sourceCode":"package issueops\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/steveyegge/beads/internal/storage\"\n)\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// AddFederationPeerInTx upserts a federation peer record. The encryptedPwd\n// should already be encrypted by the caller; pass nil for no password.\nfunc AddFederationPeerInTx(ctx context.Context, tx *sql.Tx, peer *storage.FederationPeer, encryptedPwd []byte) error {\n\tif err := ValidatePeerName(peer.Name); err != nil {\n\t\treturn fmt.Errorf(\"invalid peer name: %w\", err)\n\t}\n\n\t_, err := tx.ExecContext(ctx, `","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/federation.go#L1-L37","documentation":"ValidatePeerName checks that a federation peer name is safe to use as a Dolt remote name. An empty name is rejected immediately with this plain error. Peer names become remote identifiers, so they must be non-empty, unique-safe strings.","triggerScenarios":"Calling ValidatePeerName or AddFederationPeerInTx with name == \"\" — e.g. an unset --peer flag, empty config value, or a peer record loaded from storage with a blank name.","commonSituations":"Config file with `peer: \"\"`; environment variable for the peer name not set; constructing federation setup from templated config where the placeholder was never substituted.","solutions":["Provide a non-empty peer name when adding the federation peer (e.g. --peer alpha).","Check your config/env for the peer-name variable and set it.","Call ValidatePeerName in your setup code before AddFederationPeerInTx to fail with a clear message."],"exampleFix":"// before\nAddFederationPeerInTx(ctx, tx, cfg.PeerName, addr, nil) // PeerName may be \"\"\n// after\nif cfg.PeerName == \"\" {\n\treturn fmt.Errorf(\"--peer is required for federation setup\")\n}\nAddFederationPeerInTx(ctx, tx, cfg.PeerName, addr, nil)","handlingStrategy":"validation","validationCode":"if err := issueops.ValidatePeerName(name); err != nil {\n\treturn fmt.Errorf(\"invalid peer name %q: %w\", name, err)\n}","typeGuard":"func validPeerName(name string) bool {\n\treturn name != \"\" && len(name) <= 64 && issueopsPeerNameRe.MatchString(name) // ^[a-zA-Z][a-zA-Z0-9_-]*$\n}","tryCatchPattern":"if err := ValidatePeerName(cfg.PeerName); err != nil {\n\treturn fmt.Errorf(\"federation config: %w\", err)\n}","preventionTips":["Require --peer in federation commands instead of defaulting to empty.","Check config/env for empty peer-name values at startup.","Call ValidatePeerName during config validation, before any database work."],"tags":["validation","federation","peer-name","dolt"],"backgroundTag":"missing-required-field","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}