coleam00/Archon · error

native tool inputSchema must be an object schema with `prope

Error message

native tool inputSchema must be an object schema with `properties`

What it means

jsonSchemaToTypeBox converts a plain JSON-Schema input schema into a TypeBox object schema for Pi native tools. It refuses any inputSchema that is not an object schema with a `properties` map, because Pi native tool definitions need typed per-property schemas. The throw is an upfront fail-fast against tool definitions the provider cannot represent.

Source

Thrown at packages/providers/src/community/pi/native-tools.ts:21

import type { NativeTool } from '../../types';

function isString(v: unknown): v is string {
  return typeof v === 'string';
}

/**
 * Convert a NativeTool's canonical JSON Schema into the TypeBox schema Pi's
 * `defineTool` expects. Same narrow subset as the Claude converter (flat object
 * of strings / string-enums / booleans with `required`); anything else throws
 * (fail-fast).
 */
function jsonSchemaToTypeBox(schema: Record<string, unknown>): TObject {
  if (
    schema.type !== 'object' ||
    typeof schema.properties !== 'object' ||
    schema.properties === null
  ) {
    throw new Error('native tool inputSchema must be an object schema with `properties`');
  }
  const props = schema.properties as Record<string, Record<string, unknown>>;
  const required = new Set(
    Array.isArray(schema.required) ? (schema.required as unknown[]).filter(isString) : []
  );

  const shape: Record<string, TSchema> = {};
  for (const [key, prop] of Object.entries(props)) {
    let field: TSchema;
    if (Array.isArray(prop.enum)) {
      const values = prop.enum.filter(isString);
      if (values.length === 0) {
        throw new Error(`native tool schema: enum for '${key}' must be non-empty strings`);
      }
      field = Type.Union(values.map(v => Type.Literal(v)));
    } else if (prop.type === 'string') {
      field = Type.String();
    } else if (prop.type === 'boolean') {

View on GitHub (pinned to 0773b97458)

Solutions

  1. Change the tool's inputSchema to `{type: 'object', properties: {...}}`
  2. If the tool takes a scalar or list, wrap it: `{type:'object', properties:{ value: {type:'string'} }, required:['value']}`
  3. Validate the inputSchema with a JSON-Schema validator before registering the tool

Example fix

// before
const inputSchema = { type: 'string' };
// after
const inputSchema = { type: 'object', properties: { query: { type: 'string' } }, required: ['query'] };
Defensive patterns

Strategy: validation

Validate before calling

function isValidRootSchema(s) {
  return !!s && s.type === 'object' && typeof s.properties === 'object' && s.properties !== null;
}
if (!isValidRootSchema(tool.inputSchema)) throw new Error('tool inputSchema must be an object schema with properties');

Type guard

function isObjectSchema(s: unknown): s is { type: 'object'; properties: Record<string, unknown> } {
  return typeof s === 'object' && s !== null && (s as any).type === 'object'
    && typeof (s as any).properties === 'object' && (s as any).properties !== null;
}

Try / catch

try {
  const tools = buildPiNativeToolDefinitions(tools);
} catch (err) {
  if (err.message.includes('must be an object schema')) {
    log.error({ tool: err.message }, 'invalid native tool inputSchema');
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling buildPiNativeToolDefinitions with a tool whose inputSchema has type != 'object', lacks a `properties` key, or has `properties: null`.

Common situations: Hand-written tool schemas using top-level non-object types (e.g. `{type: 'string'}`), schemas copied from MCP servers that omit `properties`, or schemas typed as array at the root.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/4a7cb3f355d0be92. Report an issue: GitHub.