{"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":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/plugin-sdk-tamagotchi/src/tools/index.ts","lineNumber":265,"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":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/plugin-sdk-tamagotchi/src/tools/index.ts#L247-L283","documentation":"Thrown as a TypeError by serializeToolParameters() when a tool definition's inputSchema is neither a Standard Schema instance (detected by the `~standard` marker) nor a JSON Schema object (a plain object containing `type`, `properties`, `$schema`, or `$ref`). The serializer cannot convert the value into the host-safe HostDataRecord shape, so registration aborts.","triggerScenarios":"Calling toolKit.registerTool() with a definition whose inputSchema is undefined, null, a string, a number, an array, or a plain object lacking all of `type`/`properties`/`$schema`/`$ref`. Passing a raw class instance that is not a recognized schema library object also triggers it.","commonSituations":"Author forgets the inputSchema field entirely, passes a Zod/Valibot schema from a version that does not implement the Standard Schema spec, passes a JSON Schema fragment that is only a sub-schema (e.g. just `{ properties: ... }` works, but `{ description: '...' }` alone does not), or passes a wrapped object like `{ schema: ... }` instead of the schema itself.","solutions":["Pass a Valibot (or other xsschema-compatible) schema object directly as inputSchema so the `~standard` marker is present.","Or pass a JSON Schema root object that includes at least one of `type`, `properties`, `$schema`, or `$ref`.","If using a wrapped/custom schema object, unwrap it so the raw schema instance reaches registerTool.","Verify the schema library version supports Standard Schema (`~standard` property) before relying on isStandardSchema detection."],"exampleFix":"// before\nawait tools.registerTool({\n  id: 'search',\n  title: 'Search',\n  description: 'Search items',\n  inputSchema: { description: 'search params' }, // no type/properties/$schema/$ref\n  execute,\n})\n\n// after (JSON Schema)\nawait tools.registerTool({\n  id: 'search',\n  title: 'Search',\n  description: 'Search items',\n  inputSchema: { type: 'object', properties: { query: { type: 'string' } } },\n  execute,\n})\n\n// after (Valibot Standard Schema)\nimport * as v from 'valibot'\nawait tools.registerTool({\n  id: 'search',\n  title: 'Search',\n  description: 'Search items',\n  inputSchema: v.object({ query: v.string() }),\n  execute,\n})","handlingStrategy":"type-guard","validationCode":"function isValidToolInputSchema(value: unknown): boolean {\n  if (value && typeof value === 'object' && '~standard' in value) return true\n  if (value && typeof value === 'object' && !Array.isArray(value)\n      && ('type' in value || 'properties' in value || '$schema' in value || '$ref' in value)) return true\n  return false\n}\nif (!isValidToolInputSchema(definition.inputSchema)) {\n  throw new TypeError('inputSchema must be a JSON Schema object or Standard Schema instance')\n}","typeGuard":"import type { JsonSchema, Schema as StandardSchemaV1 } from 'xsschema'\n\nfunction isStandardSchema(v: unknown): v is StandardSchemaV1 {\n  return Boolean(v && typeof v === 'object' && '~standard' in v)\n}\n\nfunction isJsonSchemaRecord(v: unknown): v is JsonSchema {\n  return Boolean(v && typeof v === 'object' && !Array.isArray(v)\n    && ('type' in v || 'properties' in v || '$schema' in v || '$ref' in v))\n}","tryCatchPattern":"try {\n  await tools.registerTool(definition)\n} catch (error) {\n  if (error instanceof TypeError && /Tool input schema/.test(error.message)) {\n    // inputSchema was neither Standard Schema nor JSON Schema; fix the definition\n  } else {\n    throw error\n  }\n}","preventionTips":["Always pass a Valibot/xsschema schema or a JSON Schema root with `type`/`properties` as inputSchema.","Verify your schema library implements the Standard Schema spec (`~standard` marker) before relying on auto-conversion.","Avoid wrapping schemas in extra objects like `{ schema: ... }`; pass the schema instance directly."],"tags":["validation","json-schema","standard-schema","tool-registration","typescript"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}