{"record":{"id":"deae8cb5db0c6bb9","repo":"gastownhall/beads","slug":"invalid-remote-url-w-deae8c","errorCode":null,"errorMessage":"invalid remote URL: %w","messagePattern":"invalid remote URL: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/doltutil/remotes.go","lineNumber":162,"sourceCode":"func RemoteURLsMatch(got, want string) bool {\n\tif got == \"\" || want == \"\" {\n\t\treturn got == want\n\t}\n\tif got == want || doltremote.Normalize(got) == doltremote.Normalize(want) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// AddCLIRemote adds a remote at the filesystem level via dolt CLI.\n// Remote mutation should normally go through SQL; this is reserved for the\n// local CLI mirror required by subprocess push/pull/fetch routing.\nfunc AddCLIRemote(dbPath, name, url string) error {\n\tif err := remotecache.ValidateRemoteName(name); err != nil {\n\t\treturn fmt.Errorf(\"invalid remote name: %w\", err)\n\t}\n\tif err := remotecache.ValidateRemoteURL(url); err != nil {\n\t\treturn fmt.Errorf(\"invalid remote URL: %w\", err)\n\t}\n\tcmd := exec.Command(\"dolt\", \"remote\", \"add\", name, url) // #nosec G204 -- validated argv\n\tcmd.Dir = dbPath\n\tout, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dolt remote add failed: %s: %w\", strings.TrimSpace(string(out)), err)\n\t}\n\treturn nil\n}\n\n// RemoveCLIRemote removes a remote at the filesystem level via dolt CLI.\nfunc RemoveCLIRemote(dbPath, name string) error {\n\tif err := remotecache.ValidateRemoteName(name); err != nil {\n\t\treturn fmt.Errorf(\"invalid remote name: %w\", err)\n\t}\n\tcmd := exec.Command(\"dolt\", \"remote\", \"remove\", name) // #nosec G204 -- validated argv\n\tcmd.Dir = dbPath\n\tout, err := cmd.CombinedOutput()","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/doltutil/remotes.go#L144-L180","documentation":"AddCLIRemote validates the remote URL with remotecache.ValidateRemoteURL before shelling out to `dolt remote add`. When the URL fails validation (empty value, unsupported scheme, embedded whitespace/control characters), the function aborts without invoking dolt and wraps the validator's error with \"invalid remote URL\". This guard exists so unvalidated strings never reach the dolt subprocess argv.","triggerScenarios":"Calling AddCLIRemote or EnsureCLIRemote with a url that fails ValidateRemoteURL: an empty string, a value without a supported scheme (e.g. \"htp://...\" or a bare \"github.com/me/repo\"), or a URL containing spaces or control characters.","commonSituations":"Typo'd remote URL in beads sync config; trailing whitespace from copy-pasting a URL; passing an scp-style git URL (git@host:path) where dolt expects http(s); an unset config key interpolated as an empty string.","solutions":["Log or print the exact url value passed to EnsureCLIRemote/AddCLIRemote to see what is actually being validated","Correct the remote URL in your beads/dolt config to a full, valid http(s) URL","Trim surrounding whitespace and control characters from the configured value","If the URL looks valid, review remotecache.ValidateRemoteURL — the wrapped error states the specific rule violated"],"exampleFix":"// before\nEnsureCLIRemote(dbPath, \"origin\", \"git@github.com:me/beads.git\") // scp-style URL rejected\n\n// after\nEnsureCLIRemote(dbPath, \"origin\", \"https://github.com/me/beads.git\")","handlingStrategy":"validation","validationCode":"u, err := url.Parse(remoteURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n\treturn fmt.Errorf(\"remote URL must be absolute with a host, got %q\", remoteURL)\n}\nif strings.TrimSpace(remoteURL) != remoteURL {\n\treturn fmt.Errorf(\"remote URL has surrounding whitespace\")\n}","typeGuard":"func isValidRemoteURL(u string) bool {\n\tparsed, err := url.Parse(u)\n\treturn err == nil && (parsed.Scheme == \"http\" || parsed.Scheme == \"https\") && parsed.Host != \"\" && u == strings.TrimSpace(u)\n}","tryCatchPattern":null,"preventionTips":["Store remote URLs as full http(s) URLs in config, never scp-style git shorthand","Trim whitespace when loading URLs from env vars, flags, or config files","Validate config once at startup so bad URLs fail before any sync command runs"],"tags":["validation","dolt","remote-url","cli"],"backgroundTag":"invalid-remote-url","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}