FlowiseAI/Flowise · error · Error
Client is not initialized
Error message
Client is not initialized
What it means
Thrown inside the per-tool mapping loop in MCPToolkit.get_tools when this.client === null at the moment a tool wrapper is constructed. Because initialize() calls this.client.close() right after get_tools() returns, async scheduling can let the close (and any code that nulls the client) interleave with the still-running map callbacks, tripping the inner guard.
Source
Thrown at packages/components/nodes/tools/MCP/core.ts:190
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) {
console.error('MCP Tools failed to be resolved', errors)
}
const successes = res.filter((r) => r.status === 'fulfilled').map((r) => r.value)
return successesView on GitHub (pinned to abe4a8601a)
Solutions
- Do not call initialize() (or close()) on the same MCPToolkit concurrently; serialize lifecycle calls.
- Avoid re-invoking get_tools() manually; use the cached toolkit.tools populated by initialize().
- Use one MCPToolkit instance per session and never null its client externally.
Example fix
// before await toolkit.initialize() // closes client after get_tools await toolkit.get_tools() // client now null -> throws // after await toolkit.initialize() const tools = toolkit.tools ?? [] // use cached result
Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure no concurrent close()/initialize() runs while get_tools() executes.
if (toolkit.client === null) {
throw new Error('Refusing to call get_tools(): client was closed; create a new MCPToolkit')
} Type guard
const hasLiveClient = (tk: MCPToolkit): boolean => tk.client !== null
Try / catch
try {
return await toolkit.get_tools()
} catch (e) {
if (e.message === 'Client is not initialized') {
// build a fresh toolkit and re-initialize instead of retrying on the closed one
}
throw e
} Prevention
- Never call initialize()/close() on the same toolkit concurrently.
- Snapshot this.tools immediately after initialize() and reuse the snapshot.
- Avoid manual get_tools() calls; the cached array is already populated.
When it happens
Trigger: get_tools() is running its Promise.allSettled over tools while this.client becomes null concurrently — e.g. initialize() proceeding to client.close() or external code nulling the client mid-loop. Each tool's MCPTool() closure captures this and re-checks this.client before building the tool.
Common situations: Concurrent initialize()/close() calls on the same toolkit; a second initialize() racing the first; tool construction deferred across an await while the original client is torn down.
Related errors
- MCP server "${serverRecord.name}" is not authorized. Please
- Must initialize the toolkit first
- Missing Browserless API Token
- MCP Server Config is required
- Security validation failed: ${error.message}
AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12).
Data as JSON: /api/errors/f779f60397da4915.
Report an issue: GitHub.