abhigyanpatwari/GitNexus · error

Registry URL cannot contain query or fragment

Error message

Registry URL cannot contain query or fragment

What it means

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.

Source

Thrown at gitnexus/src/core/update-cache.ts:76

export function normalizedUpdateRegistry(env: NodeJS.ProcessEnv = process.env): {
  identity: string;
  packageUrl: string;
} {
  const key = env.npm_config_registry ?? '';
  if (registryMemo?.key === key) return registryMemo.value;
  const value = buildUpdateRegistry(key);
  registryMemo = { key, value };
  return value;
}

function buildUpdateRegistry(rawRegistry: string): { identity: string; packageUrl: string } {
  const parsed = new URL(rawRegistry || DEFAULT_UPDATE_REGISTRY);
  if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
    throw new Error('Unsupported npm registry protocol');
  }
  if (parsed.search || parsed.hash) {
    throw new Error('Registry URL cannot contain query or fragment');
  }
  parsed.username = '';
  parsed.password = '';
  parsed.pathname = parsed.pathname.replace(/\/+$/, '') || '/';

  const pathname = parsed.pathname === '/' ? '' : parsed.pathname;
  const identity = `${parsed.protocol}//${parsed.host}${pathname}`;
  // `/<pkg>/latest` is the small dist-tag document. The full packument at
  // `/<pkg>` is multi-megabyte on this package and cannot fit the fetch cap.
  const packagePath = `${pathname}/gitnexus/latest`.replace(/\/{2,}/g, '/');
  return { identity, packageUrl: `${parsed.protocol}//${parsed.host}${packagePath}` };
}

export function updateCheckCachePath(env: NodeJS.ProcessEnv = process.env): string {
  return path.join(env.GITNEXUS_HOME || getGlobalDir(), 'update-check.json');
}

export function updateCheckLockPath(env: NodeJS.ProcessEnv = process.env): string {

View on GitHub (pinned to 0d1aed942f)

Solutions

  1. Remove the query string and fragment from the configured registry URL
  2. Move authentication out of the URL into an auth token/credentials mechanism
  3. Trim the value with something like url.split('?')[0].split('#')[0] only if the query was accidental

Example fix

// before
buildUpdateRegistry('https://registry.npmjs.org/?utm_source=docs'); // throws
// after
buildUpdateRegistry('https://registry.npmjs.org');
Defensive patterns

Strategy: validation

Validate before calling

function cleanRegistry(v){ try { const p = new URL(v || 'https://registry.npmjs.org'); return !p.search && !p.hash; } catch { return false; } }

Try / catch

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; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@0d1aed942f (2026-09-08). Data as JSON: /api/errors/48eb81697d3bf12d. Report an issue: GitHub.