{"record":{"id":"70a7a2e715cb1c58","repo":"moeru-ai/airi","slug":"tool-input-schema-must-be-a-json-schema-object-or","errorCode":null,"errorMessage":"Tool input schema must be a JSON Schema object or a Standard Schema instance.","messagePattern":"Tool input schema must be a JSON Schema object or a Standard Schema instance\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/plugin-sdk-tamagotchi/src/tools/index.ts","lineNumber":269,"sourceCode":"/**\n * Normalizes tool parameter schemas into the host-safe record shape expected by plugin-sdk.\n *\n * Before:\n * - A Standard Schema instance or a JSON Schema-like authoring object\n *\n * After:\n * - A validated `HostDataRecord` safe to store in the host tool registry\n */\nasync function serializeToolParameters(inputSchema: unknown): Promise<HostDataRecord> {\n  if (isStandardSchema(inputSchema)) {\n    return toHostDataRecord(normalizeStrictToolParameterSchema(await toJsonSchema(inputSchema)))\n  }\n\n  if (isJsonSchemaRecord(inputSchema)) {\n    return toHostDataRecord(normalizeStrictToolParameterSchema(structuredClone(inputSchema)))\n  }\n\n  throw new TypeError('Tool input schema must be a JSON Schema object or a Standard Schema instance.')\n}\n\n/**\n * Exposes tamagotchi tool registration as a module-scoped extension kit.\n *\n * Use when:\n * - An extension module wants to register tools through `module.kits.use(toolKit)`\n * - The host should keep tool transport, permission, and binding details outside authoring code\n *\n * Expects:\n * - The host provides tool registry APIs when creating the kit client\n *\n * Returns:\n * - A client that registers LLM tools without depending on domain-specific kits\n */\nexport const toolKit = defineKit<ToolKitClient>({\n  id: 'kit.tool',\n  version: '1.0.0',","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/plugin-sdk-tamagotchi/src/tools/index.ts#L251-L287","documentation":"toolKit.registerTool serializes definition.inputSchema for host transport via serializeToolParameters (packages/plugin-sdk-tamagotchi/src/tools/index.ts). It accepts exactly two shapes: a Standard Schema v1 instance (detected via the '~standard' property — Zod 3.24+, Valibot v1) or a plain JSON Schema record (non-null object). Anything else — undefined, a string, an array, a class instance without '~standard', or a Zod version too old to implement Standard Schema — hits the final TypeError. The value is then normalized strictly (normalizeStrictToolParameterSchema) and stored as a HostDataRecord in the host tool registry.","triggerScenarios":"Calling registerTool({ inputSchema: ... }) with: no inputSchema field at all; a Zod schema from Zod < 3.24 (no standard-schema support); a JSON Schema passed as a JSON string; a GraphQL/typebox artifact that is neither a plain object nor Standard Schema; null.","commonSituations":"Dual-Zod setups where the extension resolves an older zod than the SDK expects; migrating from hand-written JSON Schema objects to Zod (or vice versa) and leaving one call site with a stringified schema; forgetting inputSchema for a tool that takes no arguments (use { type: 'object', properties: {} } instead of omitting).","solutions":["Pass a plain JSON Schema object: inputSchema: { type: 'object', properties: { query: { type: 'string' } }, required: ['query'] }.","Or pass a Standard Schema library instance: Zod >= 3.24 (z.object({...})) or Valibot v1 — verify the installed version actually implements Standard Schema ('~standard' in schema).","If you are on an older Zod, either upgrade or call zod-to-json-schema yourself and pass the resulting plain object.","For tools with no parameters, pass an explicit empty object schema { type: 'object', properties: {} } rather than undefined."],"exampleFix":"// before\nawait tools.registerTool({\n  id: 'weather',\n  inputSchema: JSON.stringify({ type: 'object' }), // string: throws\n})\n\n// after\nawait tools.registerTool({\n  id: 'weather',\n  inputSchema: z.object({ city: z.string() }), // Zod >= 3.24 Standard Schema\n})","handlingStrategy":"type-guard","validationCode":"function toValidInputSchema(input: unknown): object {\n  if (isStandardSchemaLike(input) || isPlainObjectSchema(input)) return input as object\n  return { type: 'object', properties: {} } // safe empty schema for no-arg tools\n}\nawait tools.registerTool({ id, title, inputSchema: toValidInputSchema(raw) })","typeGuard":"function isPlainObjectSchema(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v) && !(v instanceof Date)\n}\nfunction isStandardSchemaLike(v: unknown): v is { '~standard': { version: 1 } } {\n  return typeof v === 'object' && v !== null\n    && typeof (v as { '~standard'?: { version?: unknown } })['~standard']?.version === 'number'\n}","tryCatchPattern":"try {\n  await tools.registerTool(definition)\n} catch (error) {\n  if (error instanceof TypeError && errorMessageFrom(error).includes('Tool input schema')) {\n    // fall back to an explicit JSON Schema and register again\n    await tools.registerTool({ ...definition, inputSchema: { type: 'object', properties: {} } })\n  } else throw error\n}","preventionTips":["Standardize on Zod >= 3.24 or Valibot v1 so schemas carry the '~standard' property the SDK detects.","Never JSON.stringify schemas before passing them; pass the object itself.","Lint extension code for registerTool calls missing inputSchema — tools without parameters still need { type: 'object', properties: {} }."],"tags":["plugin-sdk","tamagotchi","tools","json-schema","validation","zod"],"backgroundTag":"schema-validation-failed","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}