{"record":{"id":"b796cce8c96143e7","repo":"ComposioHQ/composio","slug":"expected-a-z-object-schema","errorCode":null,"errorMessage":"Expected a z.object() schema.","messagePattern":"Expected a z\\.object\\(\\) schema\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ts/packages/core/src/utils/zodSchema.ts","lineNumber":78,"sourceCode":"\n  // Mirror the v4 `io` mode on the v3 converter so the two runtimes serialize `.default()`,\n  // `.transform()` and `.pipe()` schemas consistently at this boundary.\n  const converted = zodToJsonSchema.default(schema, {\n    name,\n    pipeStrategy: mode,\n    effectStrategy: mode === 'input' ? 'input' : 'any',\n  });\n\n  return stripSchemaKeyword(getNamedDefinition(converted, name));\n};\n\nexport const zodObjectSchemaToJsonSchema = (\n  schema: AnyZodSchema,\n  name: string = 'schema',\n  mode: ZodJsonSchemaMode = 'input'\n): ObjectJsonSchema => {\n  if (!isZodObjectSchema(schema)) {\n    throw new Error('Expected a z.object() schema.');\n  }\n\n  // The schema is a confirmed object and getNamedDefinition guarantees a well-formed conversion,\n  // so the result always carries `properties` (and `required` only when there are required keys).\n  const jsonSchema = zodSchemaToJsonSchema(schema, name, mode);\n\n  return {\n    type: 'object',\n    properties: (jsonSchema.properties as Record<string, unknown>) ?? {},\n    ...(jsonSchema.required ? { required: jsonSchema.required as string[] } : {}),\n  };\n};\n","sourceCodeStart":60,"sourceCodeEnd":91,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/core/src/utils/zodSchema.ts#L60-L91","documentation":"zodObjectSchemaToJsonSchema only converts Zod object schemas; passing a ZodString, ZodArray, z.union, z.any, or a wrapped/refined non-object schema throws this plain Error. Conversion to JSON Schema parameters requires a top-level object because tool parameters are named-key maps.","triggerScenarios":"Passing anything other than a z.object(...) (or .strict()/.passthrough() variant) as a tool's parameter schema to zodObjectSchemaToJsonSchema — e.g. z.record(z.string()), z.union([...]), or a ZodEffects object from .refine().","commonSituations":"Defining tool schemas as unions/records that look object-like; wrapping with .refine()/.transform() producing ZodEffects; migrating from a converter that accepted any schema.","solutions":["Ensure the top-level schema is z.object({...}) or its variants (.strict(), .passthrough(), .loose())","Move refinements to runtime validation elsewhere, or use z.object(...).superRefine only if the converter supports effects — otherwise validate inside the tool body","For union inputs, model as z.object with a discriminator field or a string field with allowed values"],"exampleFix":"// before\nconst params = z.union([z.object({ id: z.string() }), z.object({ name: z.string() })]);\n// after\nconst params = z.object({ id: z.string().optional(), name: z.string().optional() });","handlingStrategy":"type-guard","validationCode":"import { z, ZodFirstPartyTypeKind } from 'zod';\nconst isZodObject = (s: any): s is z.ZodObject<any> => s?._def?.typeName === ZodFirstPartyTypeKind.ZodObject;\nif (!isZodObject(schema)) throw new Error('Provide a z.object() schema');","typeGuard":"function isZodObjectSchema(s: unknown): s is z.ZodObject<z.ZodRawShape> { return s instanceof z.ZodObject; }","tryCatchPattern":"try { zodObjectSchemaToJsonSchema(schema); } catch (e) { if ((e as Error).message === 'Expected a z.object() schema.') { /* restructure schema */ } throw e; }","preventionTips":["Top-level tool parameter schemas must be z.object(...)","Avoid .refine()/.transform() wrappers at the top level","Use discriminated fields instead of top-level unions"],"tags":["zod","json-schema","tool-definitions","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}