ChatGPTNextWeb/NextChat · error · Error
Client ${clientId} not found
Error message
Client ${clientId} not found What it means
Thrown at app/mcp/actions.ts:344 inside executeMcpAction when clientsMap.get(clientId) is undefined OR when the entry exists but client.client is null. Unlike pause/resume (which check the config file), this checks the live in-memory clientsMap, so a server can be in the config but still trigger this if it was never initialized, was paused, or failed to initialize (client set to null with an errorMsg).
Source
Thrown at app/mcp/actions.ts:344
for (const [clientId, serverConfig] of Object.entries(config.mcpServers)) {
await initializeSingleClient(clientId, serverConfig);
}
return config;
} catch (error) {
logger.error(`Failed to restart clients: ${error}`);
throw error;
}
}
// 执行 MCP 请求
export async function executeMcpAction(
clientId: string,
request: McpRequestMessage,
) {
try {
const client = clientsMap.get(clientId);
if (!client?.client) {
throw new Error(`Client ${clientId} not found`);
}
logger.info(`Executing request for [${clientId}]`);
return await executeRequest(client.client, request);
} catch (error) {
logger.error(`Failed to execute request for [${clientId}]: ${error}`);
throw error;
}
}
// 获取 MCP 配置文件
export async function getMcpConfigFromFile(): Promise<McpConfigData> {
try {
const configStr = await fs.readFile(CONFIG_PATH, "utf-8");
return JSON.parse(configStr);
} catch (error) {
logger.error(`Failed to load MCP config, using default config: ${error}`);
return DEFAULT_MCP_CONFIG;
}View on GitHub (pinned to defdcdb55d)
Solutions
- Before executing, call getClientsStatus() and check the entry is 'active' (client present, no errorMsg).
- If the server is paused, call resumeMcpServer first and await it.
- If the server is in 'error' status, surface errorMsg to the user and offer re-add/resume rather than executing.
- Guard with a small retry/await loop keyed on initialization completion, or show a 'still initializing' message.
Example fix
// before
const result = await executeMcpAction(id, request);
// after
const status = (await getClientsStatus())[id];
if (!status || status.status !== "active") {
throw new Error(
`Client ${id} not ready (status: ${status?.status ?? "missing"}). ${status?.errorMsg ?? ""}`,
);
}
const result = await executeMcpAction(id, request); Defensive patterns
Strategy: validation
Validate before calling
import { getClientsStatus } from "@/app/mcp/actions";
async function isClientReady(clientId: string): Promise<boolean> {
const statuses = await getClientsStatus();
return statuses[clientId]?.status === "active";
}
if (await isClientReady(id)) {
const result = await executeMcpAction(id, request);
} else {
throw new Error(`Client ${id} is not ready; resume or re-add it.`);
} Type guard
type ClientStatus = { status: "active" | "paused" | "error" | "initializing"; errorMsg?: string };
function isActiveClient(
s: ClientStatus | undefined,
): s is ClientStatus & { status: "active" } {
return s?.status === "active";
} Try / catch
try {
return await executeMcpAction(id, request);
} catch (e) {
if (e instanceof Error && /not found/.test(e.message)) {
const status = (await getClientsStatus())[id];
throw new Error(
`Client ${id} not ready (status: ${status?.status ?? "missing"})`,
);
}
throw e;
} Prevention
- Never execute on a client whose status is not 'active'.
- Await initialization before exposing tools to the user.
- Auto-resume paused servers or hide their tools until resumed.
When it happens
Trigger: Calling executeMcpAction before initializeSingleClient has completed (async init still pending); calling it on a paused server (clientsMap entry was deleted on pause); calling it on a server whose createClient/listTools threw — the entry is {client:null, tools:null, errorMsg}; or on a completely unknown id.
Common situations: User invokes a tool immediately after adding a server before the async init resolves; server is in 'error' status; restartAllClients cleared the map; the worklet/client process crashed and clientsMap was not repopulated; calling execute on a paused server.
Related errors
- Server ${clientId} not found
- Failed to load tools
- Could not infer voiceLocale from voiceName!
- Failed to load preset servers
- Recording not started
AI-assisted analysis of ChatGPTNextWeb/NextChat@defdcdb55d (2026-08-12).
Data as JSON: /api/errors/d096398216e7036e.
Report an issue: GitHub.