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

  1. Remove headers from the stdio entry
  2. Pass configuration to the process via env instead (non-secret values only)
  3. 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

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


AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28). Data as JSON: /api/errors/11997e7b347057ca. Report an issue: GitHub.