abhigyanpatwari/GitNexus · error · Error
must use an SSH URL on github.com, gitlab.com, or gitee.com
Error message
must use an SSH URL on github.com, gitlab.com, or gitee.com
What it means
GitNexus auto-sync only accepts SSH-style remote URLs of the form git@host:owner/repo.git. This error is thrown by validateAutoSyncRemoteUrl when the configured remote_url does not match the required SSH regex at all — it is not HTTPS, not scp-like SSH syntax, or contains whitespace. The library throws it early (config parse / clone) to guarantee the downstream git clone command is unambiguous and safe.
Source
Thrown at gitnexus/src/core/auto-sync/config.ts:290
return {
configPath,
syncIntervalMinutes: interval,
repoGitTimeoutMs,
analyzeTimeoutMs,
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 === '..') ||View on GitHub (pinned to 0d1aed942f)
Solutions
- Replace the remote URL with scp-like SSH syntax: git@github.com:owner/repo.git (colon, not slash, after host; no scheme).
- Remove any scheme prefix (https://, ssh://) and any port segment — only git@host:path is accepted.
- Confirm the host is github.com, gitlab.com, or gitee.com — a different host will pass this check but fail the next one with 'host must be one of...'.
- Run git remote -v or `git ls-remote <url>` locally to confirm the URL works over SSH before putting it in the auto-sync config.
Example fix
// before remote_url = https://github.com/acme/widgets.git // after remote_url = git@github.com:acme/widgets.git
Defensive patterns
Strategy: validation
Validate before calling
function isValidSshRemoteUrl(url) {
const t = (url ?? '').trim();
if (t.includes('?') || t.includes('#')) return false;
return /^git@(github\.com|gitlab\.com|gitee\.com):[\w.-]+[\/][\w.\/-]+\.git$/.test(t);
}
// run before passing remote_url into the config
if (!isValidSshRemoteUrl(cfg.remote_url)) throw new Error(`bad remote_url: ${cfg.remote_url}`); Type guard
function isSshRemote(u) {
return typeof u === 'string' && /^git@[^:\s/]+:\S+$/.test(u.trim());
} Try / catch
try {
const cfg = parseAutoSyncConfig(raw);
} catch (e) {
if (String(e.message).includes('must use an SSH URL')) {
log.error(`remote_url '${cfg?.remote_url}' must be git@host:owner/repo.git`);
}
throw e;
} Prevention
- Always copy the SSH clone URL from the forge UI, never HTTPS.
- Normalize URLs through one helper before writing config.
- Keep the .git suffix; the library expects the standard scp-like form.
- Lint auto-sync config files in CI with the same regex the library uses.
When it happens
Trigger: Calling parseAutoSyncConfig with a remote_url like https://github.com/owner/repo.git, or a git:// / ssh:// prefixed URL, or an SSH URL with a port (ssh://git@github.com:22/owner/repo.git), or a URL with spaces. Also thrown by extractRepoNameFromRemoteUrl, getAutoSyncRepoIdentity, and cloneOrPull when handed the same malformed value.
Common situations: Developer copies the HTTPS clone URL from the GitHub/GitLab 'Code' button instead of the SSH one; config written before SSH keys were set up; organization moved to self-hosted GitLab with a different hostname; URL pasted with a trailing newline or embedded spaces.
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
- host must be one of github.com, gitlab.com, or gitee.com
- path must include owner/repo without traversal
- repository name must use only letters, digits, ".", "_", or
- must not be empty
- must not contain whitespace or control characters
AI-assisted analysis of abhigyanpatwari/GitNexus@0d1aed942f (2026-09-08).
Data as JSON: /api/errors/814d8360c74069d7.
Report an issue: GitHub.