nanocoai/nanoclaw · error · Error
args, env, and cwd are only valid with command
Error message
args, env, and cwd are only valid with command
What it means
Thrown when a url-based MCP entry includes `args`, `env`, or `cwd`. Those fields configure the local process for stdio transport and have no meaning for a remote HTTP endpoint, so parseMcpServerConfig rejects the combination (container-config.ts:149).
Source
Thrown at src/container-config.ts:149
// (url → http, command → stdio). "streamable-http" is the Agent Plugins
// spelling of the internal "http".
const type = input.type === 'streamable-http' ? 'http' : input.type;
if (type === 'sse') throw new Error('unsupported transport "sse"');
if (type !== undefined && type !== 'stdio' && type !== 'http') {
throw new Error('type must be "stdio", "http", or "streamable-http"');
}
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`);
}View on GitHub (pinned to 294ef2aee8)
Solutions
- Remove args/env/cwd from the url entry
- Pass server auth via headers or OneCLI credential injection, not env
- For local processes needing env, keep stdio transport with command
Example fix
// before
{"url":"https://mcp.example.com","env":{"KEY":"val"}}
// after
{"url":"https://mcp.example.com","headers":{"Authorization":"Bearer ..."}} Defensive patterns
Strategy: validation
Validate before calling
if (entry.url !== undefined) { delete entry.args; delete entry.env; delete entry.cwd; } Type guard
const isCleanHttpEntry = (e: any) => e.url !== undefined && e.args === undefined && e.env === undefined && e.cwd === undefined;
Try / catch
catch (err) { if (err.message.includes('only valid with command')) stripStdioFields(); else throw err; } Prevention
- Remember the field split: command→args/env/cwd, url→headers
- Use headers or OneCLI for http-server auth
When it happens
Trigger: An entry with url plus any of args/env/cwd, e.g. {"url":"https://...","env":{"FOO":"bar"}} via ncl or the self-mod tool.
Common situations: Copying a stdio example and swapping command for url while keeping env; trying to set env vars for a remote server via config instead of headers or OneCLI.
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
- headers is only valid with url
- 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/1f2152076949cb61.
Report an issue: GitHub.