moeru-ai/airi · error · TypeError
Tool input schema must be a JSON Schema object or a Standard
Error message
Tool input schema must be a JSON Schema object or a Standard Schema instance.
What it means
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.
Source
Thrown at packages/plugin-sdk-tamagotchi/src/tools/index.ts:265
/**
* Normalizes tool parameter schemas into the host-safe record shape expected by plugin-sdk.
*
* Before:
* - A Standard Schema instance or a JSON Schema-like authoring object
*
* After:
* - A validated `HostDataRecord` safe to store in the host tool registry
*/
async function serializeToolParameters(inputSchema: unknown): Promise<HostDataRecord> {
if (isStandardSchema(inputSchema)) {
return toHostDataRecord(normalizeStrictToolParameterSchema(await toJsonSchema(inputSchema)))
}
if (isJsonSchemaRecord(inputSchema)) {
return toHostDataRecord(normalizeStrictToolParameterSchema(structuredClone(inputSchema)))
}
throw new TypeError('Tool input schema must be a JSON Schema object or a Standard Schema instance.')
}
/**
* Exposes tamagotchi tool registration as a module-scoped extension kit.
*
* Use when:
* - An extension module wants to register tools through `module.kits.use(toolKit)`
* - The host should keep tool transport, permission, and binding details outside authoring code
*
* Expects:
* - The host provides tool registry APIs when creating the kit client
*
* Returns:
* - A client that registers LLM tools without depending on domain-specific kits
*/
export const toolKit = defineKit<ToolKitClient>({
id: 'kit.tool',
version: '1.0.0',View on GitHub (pinned to 27111382b4)
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.
Example fix
// before
await tools.registerTool({
id: 'search',
title: 'Search',
description: 'Search items',
inputSchema: { description: 'search params' }, // no type/properties/$schema/$ref
execute,
})
// after (JSON Schema)
await tools.registerTool({
id: 'search',
title: 'Search',
description: 'Search items',
inputSchema: { type: 'object', properties: { query: { type: 'string' } } },
execute,
})
// after (Valibot Standard Schema)
import * as v from 'valibot'
await tools.registerTool({
id: 'search',
title: 'Search',
description: 'Search items',
inputSchema: v.object({ query: v.string() }),
execute,
}) Defensive patterns
Strategy: type-guard
Validate before calling
function isValidToolInputSchema(value: unknown): boolean {
if (value && typeof value === 'object' && '~standard' in value) return true
if (value && typeof value === 'object' && !Array.isArray(value)
&& ('type' in value || 'properties' in value || '$schema' in value || '$ref' in value)) return true
return false
}
if (!isValidToolInputSchema(definition.inputSchema)) {
throw new TypeError('inputSchema must be a JSON Schema object or Standard Schema instance')
} Type guard
import type { JsonSchema, Schema as StandardSchemaV1 } from 'xsschema'
function isStandardSchema(v: unknown): v is StandardSchemaV1 {
return Boolean(v && typeof v === 'object' && '~standard' in v)
}
function isJsonSchemaRecord(v: unknown): v is JsonSchema {
return Boolean(v && typeof v === 'object' && !Array.isArray(v)
&& ('type' in v || 'properties' in v || '$schema' in v || '$ref' in v))
} Try / catch
try {
await tools.registerTool(definition)
} catch (error) {
if (error instanceof TypeError && /Tool input schema/.test(error.message)) {
// inputSchema was neither Standard Schema nor JSON Schema; fix the definition
} else {
throw error
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Invalid position to break block at.
- Audio stream or file is required for streaming transcription
- Invalid Godot stage scene input payload.
- Workflow error: ${errorBody.slice(0, 200)}
- ComfyUI returned no prompt_id
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/70a7a2e715cb1c58.
Report an issue: GitHub.