{"record":{"id":"68e1c2b6aa604b8f","repo":"gastownhall/beads","slug":"failed-to-canonicalize-url-w","errorCode":null,"errorMessage":"failed to canonicalize URL: %w","messagePattern":"failed to canonicalize URL: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/beads/fingerprint.go","lineNumber":70,"sourceCode":"\toutput, err := runGitInRepo(repoPath, \"config\", \"--get\", \"remote.origin.url\")\n\tif err != nil {\n\t\t// No remote configured — fall back to path-based fingerprint.\n\t\t// Use --git-common-dir to derive the main repo root so that\n\t\t// worktrees produce the same fingerprint as the main checkout.\n\t\trepoRoot, rootErr := mainRepoRootForPath(repoPath)\n\t\tif rootErr != nil {\n\t\t\treturn \"\", \"\", fmt.Errorf(\"not a git repository\")\n\t\t}\n\n\t\tnormalized := normalizedRepoPath(repoRoot)\n\t\thash := sha256.Sum256([]byte(normalized))\n\t\treturn hex.EncodeToString(hash[:16]), RepoIDSourcePath, nil\n\t}\n\n\trepoURL := strings.TrimSpace(string(output))\n\tcanonical, err := canonicalizeGitURL(repoURL)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to canonicalize URL: %w\", err)\n\t}\n\n\thash := sha256.Sum256([]byte(canonical))\n\treturn hex.EncodeToString(hash[:16]), RepoIDSourceRemote, nil\n}\n\nfunc canonicalizeGitURL(rawURL string) (string, error) {\n\trawURL = strings.TrimSpace(rawURL)\n\n\tif strings.Contains(rawURL, \"://\") {\n\t\tu, err := url.Parse(rawURL)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"invalid URL: %w\", err)\n\t\t}\n\n\t\thost := strings.ToLower(u.Hostname())\n\t\tif port := u.Port(); port != \"\" && port != \"22\" && port != \"80\" && port != \"443\" {\n\t\t\thost = host + \":\" + port","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/beads/fingerprint.go#L52-L88","documentation":"After obtaining the repository's remote URL from git, ComputeRepoIDForPathWithSource canonicalizes it (normalizing scheme, host, port, .git suffix etc.) before hashing. If canonicalizeGitURL fails, the remote URL cannot be parsed into a usable form and this wrapped error is returned, aborting remote-based fingerprinting.","triggerScenarios":"Calling ComputeRepoIDForPath on a repo whose `git remote get-url` output cannot be canonicalized — e.g. a malformed remote URL, an unparsable scheme, or unusual output from a insteadOf rewrite that canonicalizeGitURL rejects.","commonSituations":"Hand-edited .git/config with a broken URL; exotic remote helpers (e.g. `ext::` or credential-helper rewritten URLs); typos like `https:/host/repo` (single slash); corporate proxies injecting non-URL values into the remote.","solutions":["Inspect the remote URL (`git remote -v`) and fix malformed entries in .git/config","Re-set the remote: `git remote set-url origin <correct-url>`","If the URL is valid but unsupported, normalize it to a standard https:// or git@host:path form","As a workaround, ensure a clean remote is configured so path-based fallback is not needed"],"exampleFix":"// before (.git/config)\n[remote \"origin\"] url = https:/github.com/acme/repo\n// after\ngit remote set-url origin https://github.com/acme/repo.git\n","handlingStrategy":"validation","validationCode":"out, _ := exec.Command(\"git\", \"remote\", \"get-url\", \"origin\").Output()\nu := strings.TrimSpace(string(out))\nif u != \"\" && !strings.Contains(u, \"://\") && !strings.Contains(u, \":\") {\n    // fix remote before computing repo id\n}","typeGuard":null,"tryCatchPattern":"id, err := beads.ComputeRepoIDForPath(path)\nif err != nil && strings.Contains(err.Error(), \"failed to canonicalize URL\") {\n    return fmt.Errorf(\"fix remote: git remote set-url origin <url>: %w\", err)\n}","preventionTips":["Keep remotes in standard https:// or git@host:path form","Inspect `git remote -v` after editing .git/config by hand","Avoid exotic ext::/helper-based remotes for repos fingerprinted by bd","Strip whitespace before setting remote URLs"],"tags":["git","url","fingerprint"],"backgroundTag":"git-url-canonicalization-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}