Error: Type instantiation is excessively deep and possibly infinite

Hey guys, I need help…I am building a custom tool, and I am getting this error:
Type instantiation is excessively deep and possibly infinite.

On typescript… someone already passed by that?

This is the file:

import { StructuredTool } from '@langchain/core/tools';
import { z } from 'zod';
import { EntityManager } from '@mikro-orm/core';
import { SalesTransaction, TransactionStatus } from '../../../../sales/entities/sales-transaction.entity';
import { Logger } from '@nestjs/common';

// Define the input schema
export const CalculateRevenueSchema = z.object({
  startDate: z.string().describe('Start date in YYYY-MM-DD format'),
  endDate: z.string().describe('End date in YYYY-MM-DD format'),
  unitId: z.string().describe('Unit ID to calculate revenue for'),
});

export type CalculateRevenueInput = z.infer<typeof CalculateRevenueSchema>;

// Define the output schema for better type safety
export const CalculateRevenueOutputSchema = z.object({
  success: z.boolean(),
  data: z.object({
    revenue: z.number(),
    period: z.object({
      start: z.string(),
      end: z.string(),
    }),
    unitId: z.string(),
    transactionsCount: z.number(),
    formattedRevenue: z.string(),
  }),
  performance: z.object({
    executionTime: z.number(),
    queryTime: z.number(),
    toolId: z.string(),
  }),
});

export type CalculateRevenueOutput = z.infer<typeof CalculateRevenueOutputSchema>;

/**
 * Tool for calculating total revenue for a specific date range and unit
 * Refactored to use StructuredTool for proper schema handling
 */
export class CalculateRevenueTool extends StructuredTool<
  typeof CalculateRevenueSchema,
  CalculateRevenueInput,
  CalculateRevenueOutput
> {
  name = 'calculate_revenue';
  description = 'Calculate total revenue for a specific date range and business unit';
  schema = CalculateRevenueSchema; // This is the key difference!
  private readonly logger = new Logger(CalculateRevenueTool.name);

  constructor(private em: EntityManager) {
    super();
    this.logger.debug('🔧 CalculateRevenueTool initialized');
  }

  // Note: _call now receives structured input directly, not a string!
  protected async _call(input: CalculateRevenueInput): Promise<CalculateRevenueOutput> {
    const startTime = Date.now();
    const toolId = `cr-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

    this.logger.debug(`[🔧 ${toolId}] Starting revenue calculation`, {
      input,
      timestamp: new Date().toISOString(),
    });

    try {
      const { startDate, endDate, unitId } = input;

      // Validate date format
      const startDateObj = new Date(startDate);
      const endDateObj = new Date(endDate);

      if (isNaN(startDateObj.getTime()) || isNaN(endDateObj.getTime())) {
        throw new Error('Invalid date format. Use YYYY-MM-DD');
      }

      if (startDateObj > endDateObj) {
        throw new Error('Start date must be before end date');
      }

      // Calculate revenue
      this.logger.debug(`[🔧 ${toolId}] Querying transactions`, {
        unitId,
        dateRange: {
          start: startDateObj.toISOString(),
          end: endDateObj.toISOString(),
        },
        status: TransactionStatus.PAID,
      });

      const queryStartTime = Date.now();
      const transactions = await this.em.find(SalesTransaction, {
        unit: unitId,
        transactionDate: {
          $gte: startDateObj,
          $lte: endDateObj,
        },
        status: TransactionStatus.PAID,
      });

      const queryTime = Date.now() - queryStartTime;
      const revenue = transactions.reduce((sum, t) => sum + Number(t.total), 0);

      this.logger.debug(`[🔧 ${toolId}] Revenue calculation completed`, {
        transactionsFound: transactions.length,
        totalRevenue: revenue,
        queryTime,
        unitId,
      });

      const executionTime = Date.now() - startTime;

      this.logger.log(`[🔧 ${toolId}] ✅ Revenue calculated successfully`, {
        unitId,
        revenue,
        transactionsCount: transactions.length,
        period: { start: startDate, end: endDate },
        executionTime,
        queryTime,
        timestamp: new Date().toISOString(),
      });

      // Return structured data directly (not JSON string!)
      return {
        success: true,
        data: {
          revenue,
          period: { start: startDate, end: endDate },
          unitId,
          transactionsCount: transactions.length,
          formattedRevenue: new Intl.NumberFormat('pt-BR', {
            style: 'currency',
            currency: 'BRL',
          }).format(revenue),
        },
        performance: {
          executionTime,
          queryTime,
          toolId,
        },
      };
    } catch (error) {
      const executionTime = Date.now() - startTime;
      const errorMessage = error instanceof Error ? error.message : String(error);

      this.logger.error(`[🔧 ${toolId}] ❌ Revenue calculation failed`, {
        error: errorMessage,
        stack: error instanceof Error ? error.stack : undefined,
        executionTime,
        input,
        timestamp: new Date().toISOString(),
      });

      // Return error in structured format
      return {
        success: false,
        data: {
          revenue: 0,
          period: { start: input.startDate, end: input.endDate },
          unitId: input.unitId,
          transactionsCount: 0,
          formattedRevenue: 'R$ 0,00',
        },
        performance: {
          executionTime,
          queryTime: 0,
          toolId,
        },
      };
    }
  }
}

i need create the custom schema because if i didn’t do that the agent don’t know what to pass to this tool

I am using the createSupervisor and createReactAgents…

and my project is typescript

Hello! What is the zod version you have currently installed (check via npm why zod)

tamy-food/apps/api on  main [$] via 🐳 desktop-linux is 📦 v0.0.1 via  v24.4.1 on ☁️  matheus@tamy.ai 
❯ pnpm why zod       
Legend: production dependency, optional only, dev only

@tamy-food/api@0.0.1 /Users/matheusbenites/Desktop/Tamy AI/tamy-food/apps/api

dependencies:
@langchain/community 0.3.55
├─┬ @browserbasehq/stagehand 1.14.0 peer
│ ├─┬ openai 5.12.2 peer
│ │ └── zod 3.25.76 peer
│ ├── zod 3.25.76 peer
│ └─┬ zod-to-json-schema 3.24.6
│   └── zod 3.25.76 peer
├─┬ @langchain/core 0.3.75 peer
│ ├─┬ langsmith 0.3.67
│ │ └─┬ openai 5.12.2 peer
│ │   └── zod 3.25.76 peer
│ ├── zod 3.25.76
│ └─┬ zod-to-json-schema 3.24.6
│   └── zod 3.25.76 peer
└─┬ @langchain/openai 0.6.9
  ├─┬ @langchain/core 0.3.75 peer
  │ ├─┬ langsmith 0.3.67
  │ │ └─┬ openai 5.12.2 peer
  │ │   └── zod 3.25.76 peer
  │ ├── zod 3.25.76
  │ └─┬ zod-to-json-schema 3.24.6
  │   └── zod 3.25.76 peer
  └─┬ openai 5.12.2
    └── zod 3.25.76 peer

here is my version, i solved this problem disabling typescript on tool files

We’re having the same problem on zod 3.25.67. We found some similar errors on github and it said to downgrade to this version, but that ended up not fixing the issue. Removing typescript from our files fixes it but is definitely not ideal as we lose all of our typing

EDIT: It appears that it’s the schema property on the tool function’s configuration object that’s causing the issue. When i remove the schema, the error goes away on the latest version of Zod

did you found a better solution?