can1357/oh-my-pi · error

ssh://: user/port overrides are not allowed for the configur

Error message

ssh://: user/port overrides are not allowed for the configured host "${decodedBareHost}"; use ssh://${bareHost}/<path> or an unconfigured hostname

What it means

A literal user or port in an ssh:// URL is treated as an authority override on an OpenSSH destination. But a host name that matches a configured ssh.json entry is addressed only by its name — overrides would bypass the stored key/port settings and defeat the ControlMaster cache, which keys on the host name, so the handler rejects the combination.

Source

Thrown at packages/coding-agent/src/internal-urls/ssh-protocol.ts:224

	// where `url.password === ""`). `rawHost` keeps the literal marker, so it differs
	// from the canonical decoded `[user@]host[:port]` WHATWG actually parsed. Every
	// valid authority — including percent-encoded reserved-char aliases — reconstructs
	// to exactly `rawHost`, so only malformed userinfo trips this.
	const canonicalAuthority = `${url.username ? `${decodeOr(url.username)}@` : ""}${decodeOr(bareHost)}${port !== undefined ? `:${port}` : ""}`;
	if (url.rawHost !== canonicalAuthority) {
		throw new Error(
			`ssh://: unsupported or malformed authority in "${url.href}"; use ssh://[user@]host[:1-65535]/<absolute-path>`,
		);
	}
	const items = await loadConfiguredHosts(cwd);

	// A literal user/port in the URL is an authority override. A configured alias
	// is addressed only by its (percent-encoded) name, never with a separate
	// user/port — so reject an override on a configured bare name, else opaque.
	if (username || port !== undefined) {
		const decodedBareHost = decodeOr(bareHost);
		if (items.some(entry => entry.name === bareHost || entry.name === decodedBareHost)) {
			throw new Error(
				`ssh://: user/port overrides are not allowed for the configured host "${decodedBareHost}"; use ssh://${bareHost}/<path> or an unconfigured hostname`,
			);
		}
		const sshUser = username ? decodeOr(username) : undefined;
		const sshTargetHost = decodeOr(sshHost);
		const name = `${sshUser ? `${sshUser}@` : ""}${sshTargetHost}${port !== undefined ? `:${port}` : ""}`;
		return { name, host: sshTargetHost, username: sshUser, port };
	}

	// No explicit user/port: match the full decoded authority against a
	// configured name (so an encoded reserved-char alias resolves correctly).
	const match = items.find(entry => entry.name === rawAuthority) ?? items.find(entry => entry.name === bareHost);
	if (match) {
		return {
			name: match.name,
			host: match.host,
			username: match.username,
			port: match.port,

View on GitHub (pinned to 9690622007)

Solutions

  1. Address the configured host by name only: `ssh://prod/path` — its user/port come from the ssh.json entry
  2. Update the ssh.json entry if you need different user/port/key settings for that host
  3. Use a real (unconfigured) hostname with user/port for a one-off override connection

Example fix

// before
resolve('ssh://root@prod/etc/hosts') // 'prod' is a configured alias
// after
resolve('ssh://prod/etc/hosts') // or edit prod's ssh.json entry
Defensive patterns

Strategy: validation

Validate before calling

const configured = new Set((await capability.loadCapability<SSHHost>('ssh', { cwd })).items.flatMap(h => [h.name, decodeURIComponent(h.name)]));
const u = new URL(candidate);
if (u.protocol === 'ssh:' && (u.username || u.port) && configured.has(u.hostname)) throw new Error(`'${u.hostname}' is configured; address it by name without user/port overrides`);

Type guard

function isPlainConfiguredHost(u: URL, configured: Set<string>): boolean { return !(u.username || u.port) || !configured.has(u.hostname); }

Try / catch

try {
  const res = await handler.resolve(url, ctx);
} catch (e) {
  if (e instanceof Error && e.message.includes('user/port overrides are not allowed')) {
    // drop user/port and use the alias, or edit the ssh.json entry, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Resolving e.g. `ssh://root@prod/path` or `ssh://prod:2222/path` where `prod` is the `name` of an entry in the ssh.json capability file (matched against either the raw or decoded bare host).

Common situations: Trying to connect to a configured alias as a different user; assuming the alias can be parameterized with :port; forgetting that configured hosts carry their own username/port/key settings.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/df531c90107fee6b. Report an issue: GitHub.