{"record":{"id":"18da3d93b88d4d5c","repo":"nanocoai/nanoclaw","slug":"args-must-be-a-json-array-of-strings","errorCode":null,"errorMessage":"args must be a JSON array of strings","messagePattern":"args must be a JSON array of strings","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/container-config.ts","lineNumber":182,"sourceCode":"    for (const key of parsed.searchParams.keys()) {\n      if (SECRET_QUERY_KEY_RE.test(key.replace(CAMEL_SPLIT_RE, '$1_$2'))) {\n        throw new Error(`url query parameter \"${key}\" looks like a credential; use OneCLI for authentication`);\n      }\n    }\n    const headers = parseStringRecord(input.headers, 'headers');\n    return {\n      type: 'http',\n      url,\n      ...(headers === undefined ? {} : { headers }),\n      ...(instructions === undefined ? {} : { instructions }),\n    };\n  }\n  if (command === undefined) throw new Error('Provide exactly one of command or url');\n\n  if (input.headers !== undefined) throw new Error('headers is only valid with url');\n  const args = input.args ?? [];\n  if (!Array.isArray(args) || !args.every((arg) => typeof arg === 'string')) {\n    throw new Error('args must be a JSON array of strings');\n  }\n  const env = parseStringRecord(input.env, 'env') ?? {};\n  for (const key of Object.keys(env)) {\n    if (!ENV_KEY_RE.test(key)) {\n      throw new Error(`env key ${JSON.stringify(key)} must be a valid environment variable name`);\n    }\n  }\n  const cwd = parseCwd(input.cwd);\n  return {\n    command,\n    args,\n    env,\n    ...(cwd === undefined ? {} : { cwd }),\n    ...(instructions === undefined ? {} : { instructions }),\n  };\n}\n\nfunction parseStringRecord(value: unknown, flag: string): Record<string, string> | undefined {","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/container-config.ts#L164-L200","documentation":"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.","triggerScenarios":"args: \"-y server\" (string instead of array), args: [\"-y\", 42], or args: {\"0\":\"-y\"} in a stdio entry.","commonSituations":"Writing shell-style single-string args; numbers creeping in from JSON templating; a single arg passed unquoted.","solutions":["Make args a JSON array of strings: [\"-y\",\"server\"]","Quote every element; numbers must be stringified","Validate the whole entry JSON before saving"],"exampleFix":"// before\n{\"command\":\"npx\",\"args\":\"-y server\"}\n// after\n{\"command\":\"npx\",\"args\":[\"-y\",\"server\"]}","handlingStrategy":"validation","validationCode":"if (entry.args !== undefined && (!Array.isArray(entry.args) || !entry.args.every(a => typeof a === 'string'))) entry.args = entry.args.map(String);","typeGuard":"function isValidArgs(a: unknown): a is string[] { return Array.isArray(a) && a.every(x => typeof x === 'string'); }","tryCatchPattern":"catch (err) { if (err.message.includes('args must be a JSON array')) coerceArgsToArray(); else throw err; }","preventionTips":["Never pass shell-style single-string args","Stringify all numeric args at authoring time"],"tags":["mcp","config-validation","type-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}