nanocoai/nanoclaw · error · Error
url must be a valid HTTP(S) URL
Error message
url must be a valid HTTP(S) URL
What it means
new URL(url) threw while parsing the url field of an http MCP server, so parseMcpServerConfig wraps the failure as 'url must be a valid HTTP(S) URL' (the original error is attached as cause). Typical causes: missing scheme, whitespace, or a typo.
Source
Thrown at src/container-config.ts:155
}
if (type === 'stdio' && !command) throw new Error('type "stdio" requires command');
if (type === 'http' && !url) throw new Error('type "http" requires url');
const instructions = input.instructions;
if (instructions !== undefined && typeof instructions !== 'string') {
throw new Error('MCP instructions must be a string');
}
if (url !== undefined) {
if (command !== undefined) throw new Error('Provide exactly one of command or url');
if (input.args !== undefined || input.env !== undefined || input.cwd !== undefined) {
throw new Error('args, env, and cwd are only valid with command');
}
let parsed: URL;
try {
parsed = new URL(url);
} catch (err) {
throw new Error('url must be a valid HTTP(S) URL', { cause: err });
}
const loopback = ['localhost', '127.0.0.1', '[::1]', 'host.docker.internal'].includes(parsed.hostname);
if (parsed.protocol !== 'https:' && !(parsed.protocol === 'http:' && loopback)) {
throw new Error('url must use HTTPS (plain HTTP is allowed only for localhost and host.docker.internal)');
}
if (parsed.username || parsed.password || parsed.hash) {
throw new Error('url must not contain credentials or fragments; use OneCLI for authentication');
}
for (const key of parsed.searchParams.keys()) {
if (SECRET_QUERY_KEY_RE.test(key.replace(CAMEL_SPLIT_RE, '$1_$2'))) {
throw new Error(`url query parameter "${key}" looks like a credential; use OneCLI for authentication`);
}
}
const headers = parseStringRecord(input.headers, 'headers');
return {
type: 'http',
url,
...(headers === undefined ? {} : { headers }),View on GitHub (pinned to 294ef2aee8)
Solutions
- Include the full scheme: https://mcp.example.com/mcp
- Trim whitespace/newlines around the url before passing it
- Inspect err.cause in a catch block to see the underlying URL parse error
Example fix
// before
{"url":"mcp.example.com/mcp"}
// after
{"url":"https://mcp.example.com/mcp"} Defensive patterns
Strategy: validation
Validate before calling
const u = entry.url?.trim(); if (!u || !/^https?:\/\//.test(u)) throw new UserError('url must start with http(s)://'); try { new URL(u); } catch { throw new UserError('unparseable url'); } Type guard
function isParseableHttpUrl(s: unknown): s is string { if (typeof s !== 'string') return false; try { const u = new URL(s); return u.protocol === 'http:' || u.protocol === 'https:'; } catch { return false; } } Try / catch
catch (err) { if (err.message.includes('valid HTTP(S) URL')) rePromptForUrl(); else throw err; } Prevention
- Always include the scheme
- Trim whitespace before saving user-entered urls
When it happens
Trigger: url values like "mcp.example.com/mcp" (no scheme), " https://..." (leading space), or "https:\\example.com" passed in an http/streamable-http entry.
Common situations: Omitting the https:// prefix because browsers tolerate it; unescaped characters pasted from docs; trailing newline inside a shell variable.
Related errors
- type "stdio" requires command
- type "http" requires url
- MCP instructions must be a string
- Provide exactly one of command or url
- args, env, and cwd are only valid with command
AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28).
Data as JSON: /api/errors/2bcb631121c38ae5.
Report an issue: GitHub.