{"record":{"id":"ddef898911cc4d9c","repo":"gastownhall/beads","slug":"remote-url-cannot-be-empty","errorCode":null,"errorMessage":"remote URL cannot be empty","messagePattern":"remote URL cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/remotecache/url.go","lineNumber":81,"sourceCode":"func IsRemoteURL(s string) bool {\n\tfor _, scheme := range remoteSchemes {\n\t\tif strings.HasPrefix(s, scheme) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn gitSSHPattern.MatchString(s)\n}\n\n// ValidateRemoteURL performs strict security validation on a remote URL.\n// It rejects URLs containing control characters (including null bytes),\n// validates structural correctness per scheme, and rejects leading dashes\n// that could be interpreted as CLI flags.\n//\n// This is a security boundary — all remote URLs should pass through this\n// before reaching exec.Command arguments or SQL parameters.\nfunc ValidateRemoteURL(rawURL string) error {\n\tif rawURL == \"\" {\n\t\treturn fmt.Errorf(\"remote URL cannot be empty\")\n\t}\n\n\t// Reject control characters (null bytes, newlines, tabs, etc.)\n\tfor i, c := range rawURL {\n\t\tif c < 0x20 || c == 0x7f {\n\t\t\treturn fmt.Errorf(\"remote URL contains control character at position %d (0x%02x)\", i, c)\n\t\t}\n\t}\n\n\t// Reject leading dash (CLI flag injection via exec.Command arguments)\n\tif strings.HasPrefix(rawURL, \"-\") {\n\t\treturn fmt.Errorf(\"remote URL must not start with a dash\")\n\t}\n\n\t// SCP-style URLs (user@host:path) are validated separately\n\tif gitSSHPattern.MatchString(rawURL) {\n\t\treturn validateSCPURL(rawURL)\n\t}","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/remotecache/url.go#L63-L99","documentation":"ValidateRemoteURL() is the package's security boundary: every remote URL must pass it before being used in exec.Command arguments or SQL parameters. This error fires first when the URL string is empty — there is nothing to validate or clone from.","triggerScenarios":"Cache.Ensure(ctx, \"\") or ValidateRemoteURL(\"\") / ValidateRemoteURLWithPatterns(\"\", ...) with an unset remote URL — typically a missing config value, empty env var, or a function receiving an uninitialized variable.","commonSituations":"bd config file missing the remote/peer URL field; environment variable (e.g. for the remote) empty in CI; a code path building the URL from parts where the variable part resolved to empty; deserialized config with a blank value.","solutions":["Set the remote URL before calling: e.g. dolthub://org/repo in bd config or the relevant env var.","Check where the value originates (config file key present and non-empty, env var set) and fail fast with a clearer upstream message.","Guard callers: skip cache operations entirely when no remote is configured instead of passing an empty string.","Run `bd doctor`/config inspection to confirm the remote is configured."],"exampleFix":"// before: calling with possibly-empty config value\n_, err := cache.Ensure(ctx, cfg.RemoteURL)\n// after: fail early with a clear message\nif cfg.RemoteURL == \"\" {\n    return fmt.Errorf(\"no remote configured: set remote_url in .beads/beads.json\")\n}\n_, err := cache.Ensure(ctx, cfg.RemoteURL)","handlingStrategy":"validation","validationCode":"func validateBeforeUse(remoteURL string) error {\n    if strings.TrimSpace(remoteURL) == \"\" {\n        return fmt.Errorf(\"remote URL is not configured\")\n    }\n    return remotecache.ValidateRemoteURL(remoteURL)\n}","typeGuard":null,"tryCatchPattern":"if err := validateBeforeUse(cfg.RemoteURL); err != nil {\n    return fmt.Errorf(\"check .beads/beads.json remote_url: %w\", err)\n}\nreturn cache.Ensure(ctx, cfg.RemoteURL)","preventionTips":["Validate config at load time; fail with a clear 'remote not configured' message instead of a empty URL reaching the cache.","Avoid the zero-value trap: never pass an unset string variable as remoteURL.","Check env vars with os.LookupEnv to distinguish unset from empty.","Document the expected URL format (dolthub://org/repo) in config examples."],"tags":["go","validation","security","configuration"],"backgroundTag":"missing-remote-url","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}