{"record":{"id":"ec207f6ee47be01e","repo":"abhigyanpatwari/GitNexus","slug":"must-not-include-query-strings-or-fragments","errorCode":null,"errorMessage":"must not include query strings or fragments","messagePattern":"must not include query strings or fragments","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/auto-sync/config.ts","lineNumber":286,"sourceCode":"    });\n  }\n\n  if (errors.length > 0) throw new Error(errors.join('; '));\n  return {\n    configPath,\n    syncIntervalMinutes: interval,\n    repoGitTimeoutMs,\n    analyzeTimeoutMs,\n    maxConcurrency,\n    analyzeFailureThreshold,\n    projects,\n  };\n}\n\nexport function validateAutoSyncRemoteUrl(remoteUrl: string): void {\n  const trimmed = remoteUrl.trim();\n  if (trimmed.includes('?') || trimmed.includes('#')) {\n    throw new Error('must not include query strings or fragments');\n  }\n  const match = /^git@([^:\\s/]+):([^\\s]+)$/.exec(trimmed);\n  if (!match) {\n    throw new Error('must use an SSH URL on github.com, gitlab.com, or gitee.com');\n  }\n  const host = match[1].toLowerCase();\n  const repoPath = match[2];\n  if (!ALLOWED_REMOTE_HOSTS.has(host)) {\n    throw new Error('host must be one of github.com, gitlab.com, or gitee.com');\n  }\n  const pathParts = repoPath.split('/');\n  // Every segment becomes a directory component: the namespace segments build\n  // the clone path and the last one names the repo. So each is held to the same\n  // charset, which is what keeps a separator out of a segment — on Windows\n  // `..\\..\\outside` is traversal even though the segment is not literally `..`,\n  // and testing the raw string for `..` instead would reject an ordinary\n  // `foo..bar`. Traversal is a whole segment; a separator is a character.\n  const namespaceParts = pathParts.slice(0, -1);","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/core/auto-sync/config.ts#L268-L304","documentation":"validateAutoSyncRemoteUrl() rejects remote URLs containing '?' or '#' because query strings and fragments are meaningless in git SSH remotes and would corrupt repo identity/clone URL derivation. The message is thrown before the SSH-URL format check, so it fires for any remote containing those characters.","triggerScenarios":"Configuring an auto-sync remote like git@github.com:org/repo.git?ref=main or a URL copied from a web page that includes #readme, or a stale HTTPS-style URL pasted into the SSH remotes list.","commonSituations":"Copy-pasting the browser URL (with #fragment) instead of the git clone URL, appending branch/query parameters to a remote, or template strings that leaked '?' into the config.","solutions":["Strip everything from '?' onward in the remote URL.","Strip everything from '#' onward in the remote URL.","Use the plain SSH form: git@github.com:org/repo.git (allowed hosts: github.com, gitlab.com, gitee.com).","If you need a specific branch, configure it via the auto-sync branch option, not the URL.","Fix the source script/template that injected the query or fragment."],"exampleFix":"// before\nremotes:\n  - git@github.com:org/repo.git?ref=main\n// after\nremotes:\n  - git@github.com:org/repo.git","handlingStrategy":"validation","validationCode":"for (const url of cfg.remotes) {\n  if (url.includes('?') || url.includes('#')) throw new Error(`remote ${url} must not contain ? or #`);\n  if (!/^git@[^:\\s/]+:[^\\s]+$/.test(url.trim())) throw new Error(`remote ${url} must be an SSH URL`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy the git clone (SSH) URL, never the browser address bar URL","Never append ?query or #fragment to git remotes","Use only github.com, gitlab.com, or gitee.com SSH hosts","Sanitize URL-building templates that could leak '?' placeholders"],"tags":["git","remote-url","auto-sync","validation"],"backgroundTag":"invalid-url-format","analyzedSha":"0d1aed942f0e8b5d3bac27519fff441aceea722d","analyzedAt":"2026-09-08T00:40:44.970Z","contentChangedAt":"2026-09-08T00:40:44.970Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}