{"record":{"id":"079ee69d4c34d377","repo":"nexu-io/open-design","slug":"inputs-must-be-an-object","errorCode":null,"errorMessage":"inputs must be an object","messagePattern":"inputs must be an object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/mcp.ts","lineNumber":2536,"sourceCode":"  if (args.resume !== undefined) {\n    if (typeof args.resume !== 'boolean') throw new Error('resume must be a boolean');\n    body.resume = args.resume;\n  }\n  if (typeof args.prompt === 'string' && args.prompt.length > 0) {\n    body.message = args.prompt;\n    body.currentPrompt = args.prompt;\n  }\n  if (typeof args.skill === 'string' && args.skill.length > 0) body.skillId = args.skill;\n  if (Array.isArray(args.skills) && args.skills.length > 0) body.skillIds = args.skills;\n  if (typeof args.plugin === 'string' && args.plugin.length > 0) body.pluginId = args.plugin;\n  if (typeof args.agent === 'string' && args.agent.length > 0) body.agentId = args.agent;\n  if (typeof args.model === 'string' && args.model.length > 0) body.model = args.model;\n  if (typeof args.serviceTier === 'string' && args.serviceTier.length > 0) {\n    body.serviceTier = args.serviceTier;\n  }\n  if (args.inputs !== undefined) {\n    if (args.inputs === null || typeof args.inputs !== 'object' || Array.isArray(args.inputs)) {\n      throw new Error('inputs must be an object');\n    }\n    body.pluginInputs = args.inputs;\n  }\n  const created = await postJson<JsonObject>(\n    `${baseUrl}/api/runs`,\n    body,\n    { ...options.analyticsHeaders, ...headers },\n  );\n  // Build studioUrl (conversation-level — no entry file yet) so the\n  // outer agent has a URL to give the user right away. The daemon\n  // returns conversationId in the response now that POST /api/runs\n  // falls back to the project's default conversation for MCP callers.\n  const webBase = await getWebBaseUrl(baseUrl);\n  const studioUrl = buildStudioUrl(webBase, id, created?.conversationId, null);\n  return ok(\n    withActiveEcho(\n      {\n        ...created,","sourceCodeStart":2518,"sourceCodeEnd":2554,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/mcp.ts#L2518-L2554","documentation":"Thrown by the MCP run-start helper while building POST /api/runs. The `inputs` argument becomes `body.pluginInputs`, a key/value map passed to the resolved plugin. The guard rejects null, arrays, and primitives because plugin input resolution expects a plain object; a non-object would either crash later dispatch or be silently mis-applied.","triggerScenarios":"Calling start_run with `inputs: [{...}]` (array of objects), `inputs: null`, `inputs: \"{\"k\":1}\"` (a JSON string), or `inputs: \"\"`. Common when a caller wraps inputs in an extra array layer or forgets to JSON.parse a serialized payload.","commonSituations":"LLM tool-call args serialized as arrays by mistake; config files that store inputs as a JSON string; passing the whole plugin snapshot instead of its `.inputs` field.","solutions":["Pass a plain object: `inputs: { field: value }`.","If you hold a JSON string, parse first: `inputs: JSON.parse(raw)`.","If you have an array of one object, unwrap it: `inputs: arr[0]`.","Omit `inputs` when the plugin takes no inputs rather than passing `null`."],"exampleFix":"// before\n{ plugin: id, inputs: [{ tone: \"bold\" }] }\n// after\n{ plugin: id, inputs: { tone: \"bold\" } }","handlingStrategy":"type-guard","validationCode":"if (inputs !== undefined && (inputs === null || typeof inputs !== 'object' || Array.isArray(inputs))) {\n  throw new TypeError('inputs must be a plain object');\n}","typeGuard":"function isPlainObject(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":null,"preventionTips":["Type plugin inputs as Record<string, unknown> in your client.","JSON.parse serialized inputs before passing them.","Never wrap inputs in an array."],"tags":["mcp","validation","plugins","input-coercion"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}