{"record":{"id":"e1c5edf21d8d9428","repo":"nexu-io/open-design","slug":"resume-must-be-a-boolean","errorCode":null,"errorMessage":"resume must be a boolean","messagePattern":"resume must be a boolean","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/mcp.ts","lineNumber":2519,"sourceCode":"        options.analyticsHeaders?.[ANALYTICS_HEADER_HOST_PRODUCT] ?? 'unknown',\n      externalPluginId: options.pluginAttribution.context.id,\n      externalPluginVersion:\n        options.pluginAttribution.context.version,\n      distributionMechanism:\n        options.pluginAttribution.context.distributionMechanism,\n      publisherClass: options.pluginAttribution.context.publisherClass,\n      // This payload is client-supplied. The daemon validates it against the\n      // request identity/digest and upgrades to session_correlated only after\n      // the Run/workflow binding is accepted.\n      attributionQuality: 'self_reported',\n      pluginWorkflowId: options.pluginAttribution.pluginWorkflowId,\n      logicalRequestDigest: logical.digest,\n      logicalRequestDigestVersion: logical.version,\n      briefState: options.briefState ?? 'not_applicable',\n    };\n  }\n  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    }","sourceCodeStart":2501,"sourceCodeEnd":2537,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/mcp.ts#L2501-L2537","documentation":"Thrown by the MCP run-start helper in apps/daemon/src/mcp.ts while assembling the body for POST /api/runs. When the caller supplies a `resume` field it must already be a JS boolean; the MCP layer refuses to coerce strings/numbers because `resume:true` has billing and idempotency side effects (resuming a paused Cloud run via requestId). The guard runs before the request is sent, so no daemon round trip occurs.","triggerScenarios":"Calling the start_run MCP tool with `resume: \"true\"`, `resume: 1`, or `resume: \"yes\"` instead of the literal boolean `true`. Also happens when a client JSON-parses config into a string field, or when an agent emits resume as an enum string.","commonSituations":"Agent/LLM tool-call arguments arrive as strings from JSON schemas that declare resume as string; shell-driven MCP clients passing `--resume true`; copying a requestId-based retry payload from docs that quote the boolean.","solutions":["Pass `resume` as a literal boolean: `resume: true` (or `false`), never quoted.","If the value comes from untyped JSON, coerce before the call: `resume: Boolean(value)` only when you actually intend to resume.","Omit `resume` entirely when you are not resuming a paused Cloud run — the field is optional.","Re-check that requestId is the exact original logical-run id when resuming; resume without it starts a fresh run."],"exampleFix":"// before\n{ requestId: id, resume: \"true\" }\n// after\n{ requestId: id, resume: true }","handlingStrategy":"type-guard","validationCode":"const resume = args.resume;\nif (resume !== undefined && typeof resume !== 'boolean') {\n  throw new TypeError('resume must be boolean, got ' + typeof resume);\n}","typeGuard":"function isResume(v: unknown): v is boolean | undefined {\n  return v === undefined || typeof v === 'boolean';\n}","tryCatchPattern":null,"preventionTips":["Declare resume as `boolean` (not string) in your MCP tool's JSON schema.","Coerce untyped config with `Boolean()` only when resuming is intended.","Omit resume for fresh runs rather than passing false explicitly to avoid confusion."],"tags":["mcp","validation","input-coercion","runs"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}