abhigyanpatwari/GitNexus · error · Error

host must be one of github.com, gitlab.com, or gitee.com

Error message

host must be one of github.com, gitlab.com, or gitee.com

What it means

After the URL parses as SSH syntax, validateAutoSyncRemoteUrl checks the host portion against the allowlist ALLOWED_REMOTE_HOSTS (github.com, gitlab.com, gitee.com, case-insensitive). This error means the URL is valid SSH syntax but points at an unsupported host. Auto-sync only supports these three forges, so any other host is rejected before a clone is attempted.

Source

Thrown at gitnexus/src/core/auto-sync/config.ts:295

    maxConcurrency,
    analyzeFailureThreshold,
    projects,
  };
}

export function validateAutoSyncRemoteUrl(remoteUrl: string): void {
  const trimmed = remoteUrl.trim();
  if (trimmed.includes('?') || trimmed.includes('#')) {
    throw new Error('must not include query strings or fragments');
  }
  const match = /^git@([^:\s/]+):([^\s]+)$/.exec(trimmed);
  if (!match) {
    throw new Error('must use an SSH URL on github.com, gitlab.com, or gitee.com');
  }
  const host = match[1].toLowerCase();
  const repoPath = match[2];
  if (!ALLOWED_REMOTE_HOSTS.has(host)) {
    throw new Error('host must be one of github.com, gitlab.com, or gitee.com');
  }
  const pathParts = repoPath.split('/');
  // Every segment becomes a directory component: the namespace segments build
  // the clone path and the last one names the repo. So each is held to the same
  // charset, which is what keeps a separator out of a segment — on Windows
  // `..\..\outside` is traversal even though the segment is not literally `..`,
  // and testing the raw string for `..` instead would reject an ordinary
  // `foo..bar`. Traversal is a whole segment; a separator is a character.
  const namespaceParts = pathParts.slice(0, -1);
  if (
    repoPath.startsWith('/') ||
    pathParts.length < 2 ||
    pathParts.some((part) => !part || part === '.' || part === '..') ||
    namespaceParts.some((part) => !REMOTE_PATH_SEGMENT_PATTERN.test(part))
  ) {
    throw new Error('path must include owner/repo without traversal');
  }
  // The final segment becomes the on-disk clone directory via `extractRepoName`,

View on GitHub (pinned to 0d1aed942f)

Solutions

  1. Move the repo to (or mirror it into) github.com, gitlab.com, or gitee.com and use that URL.
  2. If you must keep the private host, exclude this project from auto-sync and sync it manually with git pull / the standard workflow.
  3. Check for typos in the host (e.g. gitlab.cm instead of gitlab.com) that fall outside the allowlist.
  4. Verify you are not accidentally including a port or subdomain in the host portion (git@github.com:22:... will not match).

Example fix

// before
remote_url = git@gitlab.mycompany.com:acme/widgets.git
// after
remote_url = git@gitlab.com:acme/widgets.git
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = new Set(['github.com', 'gitlab.com', 'gitee.com']);
function hostIsAllowed(url) {
  const m = /^git@([^:\s/]+):/.test(url) ;
  if (!m) return false;
  const host = url.trim().match(/^git@([^:\s/]+):/)[1].toLowerCase();
  return ALLOWED.has(host);
}
if (!hostIsAllowed(cfg.remote_url)) throw new Error('unsupported forge host');

Type guard

function isAllowedHost(u) {
  const m = /^git@([^:\s/]+):/.exec(typeof u === 'string' ? u.trim() : '');
  return !!m && ['github.com','gitlab.com','gitee.com'].includes(m[1].toLowerCase());
}

Try / catch

try {
  validateAutoSyncRemoteUrl(remoteUrl);
} catch (e) {
  if (String(e.message).includes('host must be one of')) {
    log.error(`Auto-sync only supports github.com, gitlab.com, gitee.com; got '${remoteUrl}'`);
  }
  throw e;
}

Prevention

When it happens

Trigger: remote_url = git@bitbucket.org:acme/widgets.git, a self-hosted GitLab (git@gitlab.mycompany.com:acme/widgets.git), GitHub Enterprise (git@github.acme.io:...), or SSH URLs with a capitalized host that still resolves to a non-allowed host (host check is on the actual string, lowercased).

Common situations: Company hosts code on GitHub Enterprise or self-hosted GitLab; developer mistakenly configures a Bitbucket repo; mirror setups pointing at an internal git server.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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