{"record":{"id":"48eb81697d3bf12d","repo":"abhigyanpatwari/GitNexus","slug":"registry-url-cannot-contain-query-or-fragment","errorCode":null,"errorMessage":"Registry URL cannot contain query or fragment","messagePattern":"Registry URL cannot contain query or fragment","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/update-cache.ts","lineNumber":76,"sourceCode":"\nexport function normalizedUpdateRegistry(env: NodeJS.ProcessEnv = process.env): {\n  identity: string;\n  packageUrl: string;\n} {\n  const key = env.npm_config_registry ?? '';\n  if (registryMemo?.key === key) return registryMemo.value;\n  const value = buildUpdateRegistry(key);\n  registryMemo = { key, value };\n  return value;\n}\n\nfunction buildUpdateRegistry(rawRegistry: string): { identity: string; packageUrl: string } {\n  const parsed = new URL(rawRegistry || DEFAULT_UPDATE_REGISTRY);\n  if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n    throw new Error('Unsupported npm registry protocol');\n  }\n  if (parsed.search || parsed.hash) {\n    throw new Error('Registry URL cannot contain query or fragment');\n  }\n  parsed.username = '';\n  parsed.password = '';\n  parsed.pathname = parsed.pathname.replace(/\\/+$/, '') || '/';\n\n  const pathname = parsed.pathname === '/' ? '' : parsed.pathname;\n  const identity = `${parsed.protocol}//${parsed.host}${pathname}`;\n  // `/<pkg>/latest` is the small dist-tag document. The full packument at\n  // `/<pkg>` is multi-megabyte on this package and cannot fit the fetch cap.\n  const packagePath = `${pathname}/gitnexus/latest`.replace(/\\/{2,}/g, '/');\n  return { identity, packageUrl: `${parsed.protocol}//${parsed.host}${packagePath}` };\n}\n\nexport function updateCheckCachePath(env: NodeJS.ProcessEnv = process.env): string {\n  return path.join(env.GITNEXUS_HOME || getGlobalDir(), 'update-check.json');\n}\n\nexport function updateCheckLockPath(env: NodeJS.ProcessEnv = process.env): string {","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/core/update-cache.ts#L58-L94","documentation":"buildUpdateRegistry rejects registry URLs that contain a query string or fragment, throwing this error. Update-cache derives a cache identity and package URL from the registry URL; query/fragment components would make the derived identity ambiguous or the package URL malformed, so they are forbidden outright. Credentials (userinfo) are silently stripped rather than rejected.","triggerScenarios":"Configuring a registry like 'https://registry.example.com?team=x' or 'https://registry.example.com/#stable' — any URL where parsed.search or parsed.hash is non-empty.","commonSituations":"Copy-pasting a registry URL from a browser address bar that carried a search or anchor; appending access tokens as query parameters to a registry URL (tokens belong in auth headers, not the URL); trailing template placeholders left in config.","solutions":["Remove the query string and fragment from the configured registry URL","Move authentication out of the URL into an auth token/credentials mechanism","Trim the value with something like url.split('?')[0].split('#')[0] only if the query was accidental"],"exampleFix":"// before\nbuildUpdateRegistry('https://registry.npmjs.org/?utm_source=docs'); // throws\n// after\nbuildUpdateRegistry('https://registry.npmjs.org');","handlingStrategy":"validation","validationCode":"function cleanRegistry(v){ try { const p = new URL(v || 'https://registry.npmjs.org'); return !p.search && !p.hash; } catch { return false; } }","typeGuard":null,"tryCatchPattern":"try { cache = buildUpdateRegistry(registryRaw); } catch (e) { if (e.message.includes('query or fragment')) { registryRaw = registryRaw.split('?')[0].split('#')[0]; cache = buildUpdateRegistry(registryRaw); } else throw e; }","preventionTips":["Strip ?... and #... before saving registry URLs","Keep auth tokens in headers/.npmrc auth config, never in the URL","Avoid copying registry URLs from browser address bars"],"tags":["npm","registry","config","url"],"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"}