FlowiseAI/Flowise · error · Error

Must initialize the toolkit first

Error message

Must initialize the toolkit first

What it means

Thrown by MCPToolkit.get_tools when this._tools === null OR this.client === null. get_tools reads this._tools.tools and maps over them, so both the cached tool list and a live client must exist. initialize() is the only method that sets this._tools and this.client; calling get_tools() before initialize() (or after the client was closed and nulled) violates that precondition.

Source

Thrown at packages/components/nodes/tools/MCP/core.ts:186

        return client
    }

    async initialize() {
        if (this._tools === null) {
            this.client = await this.createClient()

            this._tools = await this.client.request({ method: 'tools/list' }, ListToolsResultSchema)

            this.tools = await this.get_tools()

            // Close the initial client after initialization
            await this.client.close()
        }
    }

    async get_tools(): Promise<Tool[]> {
        if (this._tools === null || this.client === null) {
            throw new Error('Must initialize the toolkit first')
        }
        const toolsPromises = this._tools.tools.map(async (tool: any) => {
            if (this.client === null) {
                throw new Error('Client is not initialized')
            }
            const argsSchema = tool.inputSchema ?? { type: 'object', properties: {} }
            const safeName = sanitizeMCPToolName(tool.name)
            const safeDescription = sanitizeMCPToolDescription(tool.description || tool.name)
            return await MCPTool({
                toolkit: this,
                name: safeName,
                description: safeDescription,
                argsSchema
            })
        })
        const res = await Promise.allSettled(toolsPromises)
        const errors = res.filter((r) => r.status === 'rejected')
        if (errors.length !== 0) {

View on GitHub (pinned to abe4a8601a)

Solutions

  1. Always await toolkit.initialize() before calling get_tools() (or rely on initialize() which already populates toolkit.tools).
  2. Read toolkit.tools (the cached array) instead of calling get_tools() again.
  3. Construct a fresh MCPToolkit per session rather than reusing one whose client was closed.

Example fix

// before
const toolkit = new MCPToolkit(params, 'stdio')
const tools = await toolkit.get_tools() // throws: not initialized

// after
const toolkit = new MCPToolkit(params, 'stdio')
await toolkit.initialize()
const tools = toolkit.tools ?? []
Defensive patterns

Strategy: try-catch

Validate before calling

if (toolkit._tools === null || toolkit.client === null) {
  await toolkit.initialize()
}
const tools = toolkit.tools ?? []

Type guard

const isInitialized = (tk: MCPToolkit): boolean => tk._tools !== null && tk.client !== null

Try / catch

try {
  return await toolkit.get_tools()
} catch (e) {
  if (e.message === 'Must initialize the toolkit first') {
    await toolkit.initialize()
    return toolkit.tools ?? []
  }
  throw e
}

Prevention

When it happens

Trigger: Calling toolkit.get_tools() before toolkit.initialize(); or calling it again after the toolkit's client was closed/null. Note initialize() itself calls get_tools() internally, so manual calls are usually redundant.

Common situations: Subclass or caller that calls get_tools() directly to refresh the tool list; race where initialize() threw midway leaving _tools null; reusing a toolkit across requests after close().

Related errors


AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12). Data as JSON: /api/errors/4258e5310af6f210. Report an issue: GitHub.