nanocoai/nanoclaw · error · Error
headers is only valid with url
Error message
headers is only valid with url
What it means
A stdio (command-based) MCP entry includes a `headers` field. Headers only apply to url/http transport; for a local process they are meaningless, so parseMcpServerConfig rejects them (container-config.ts:179).
Source
Thrown at src/container-config.ts:179
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 }),
...(instructions === undefined ? {} : { instructions }),
};
}
if (command === undefined) throw new Error('Provide exactly one of command or url');
if (input.headers !== undefined) throw new Error('headers is only valid with url');
const args = input.args ?? [];
if (!Array.isArray(args) || !args.every((arg) => typeof arg === 'string')) {
throw new Error('args must be a JSON array of strings');
}
const env = parseStringRecord(input.env, 'env') ?? {};
for (const key of Object.keys(env)) {
if (!ENV_KEY_RE.test(key)) {
throw new Error(`env key ${JSON.stringify(key)} must be a valid environment variable name`);
}
}
const cwd = parseCwd(input.cwd);
return {
command,
args,
env,
...(cwd === undefined ? {} : { cwd }),
...(instructions === undefined ? {} : { instructions }),
};View on GitHub (pinned to 294ef2aee8)
Solutions
- Remove headers from the stdio entry
- Pass configuration to the process via env instead (non-secret values only)
- Store real credentials in OneCLI, never in headers/env config
Example fix
// before
{"command":"npx","args":["srv"],"headers":{"X-Api-Key":"k"}}
// after
{"command":"npx","args":["srv"]} Defensive patterns
Strategy: validation
Validate before calling
if (entry.command !== undefined) delete entry.headers;
Type guard
const isCleanStdioEntry = (e: any) => e.command !== undefined && e.headers === undefined;
Try / catch
catch (err) { if (err.message.includes('headers is only valid with url')) stripHeaders(); else throw err; } Prevention
- Remember headers belong to url transport only
- Use env for process config, OneCLI for secrets
When it happens
Trigger: {"command":"npx","args":[...],"headers":{"Authorization":"..."}} passed via ncl add-mcp-server or the self-mod tool.
Common situations: Converting an http entry to stdio and leaving headers behind; attempting to pass auth to the wrapped process via headers instead of env.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- args, env, and cwd are only valid with command
- type "stdio" requires command
- type "http" requires url
- MCP instructions must be a string
- Provide exactly one of command or url
AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28).
Data as JSON: /api/errors/11997e7b347057ca.
Report an issue: GitHub.