nanocoai/nanoclaw · error · Error

args must be a JSON array of strings

Error message

args must be a JSON array of strings

What it means

The `args` field of a stdio MCP entry is not an array of strings (or is not an array at all — args defaults to [] only when undefined). Non-string args would be passed to a child process spawn and fail confusingly later, so the shape is validated here.

Source

Thrown at src/container-config.ts:182

    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 }),
  };
}

function parseStringRecord(value: unknown, flag: string): Record<string, string> | undefined {

View on GitHub (pinned to 294ef2aee8)

Solutions

  1. Make args a JSON array of strings: ["-y","server"]
  2. Quote every element; numbers must be stringified
  3. Validate the whole entry JSON before saving

Example fix

// before
{"command":"npx","args":"-y server"}
// after
{"command":"npx","args":["-y","server"]}
Defensive patterns

Strategy: validation

Validate before calling

if (entry.args !== undefined && (!Array.isArray(entry.args) || !entry.args.every(a => typeof a === 'string'))) entry.args = entry.args.map(String);

Type guard

function isValidArgs(a: unknown): a is string[] { return Array.isArray(a) && a.every(x => typeof x === 'string'); }

Try / catch

catch (err) { if (err.message.includes('args must be a JSON array')) coerceArgsToArray(); else throw err; }

Prevention

When it happens

Trigger: args: "-y server" (string instead of array), args: ["-y", 42], or args: {"0":"-y"} in a stdio entry.

Common situations: Writing shell-style single-string args; numbers creeping in from JSON templating; a single arg passed unquoted.

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/18da3d93b88d4d5c. Report an issue: GitHub.