{"record":{"id":"f6b67920359c8297","repo":"lobehub/lobehub","slug":"not-found-f6b679","errorCode":"NOT_FOUND","errorMessage":"Bot not found: ${botId}","messagePattern":"Bot not found: (.+?)","errorType":"exception","errorClass":"TRPCError","httpStatus":404,"severity":"error","filePath":"apps/server/src/routers/lambda/botMessage.ts","lineNumber":147,"sourceCode":"\nconst createServiceForBot = (provider: DecryptedBotProvider): MessageRuntimeService =>\n  createServiceForCredentials(\n    provider.platform,\n    provider.applicationId,\n    provider.credentials as Record<string, any>,\n  );\n\nconst resolveBot = async (\n  model: AgentBotProviderModel,\n  botId: string,\n): Promise<{\n  platform: MessagePlatformType;\n  service: MessageRuntimeService;\n  settings: Record<string, unknown>;\n}> => {\n  const provider = await model.findById(botId);\n  if (!provider) {\n    throw new TRPCError({ code: 'NOT_FOUND', message: `Bot not found: ${botId}` });\n  }\n  if (!provider.enabled) {\n    throw new TRPCError({ code: 'BAD_REQUEST', message: `Bot is disabled: ${botId}` });\n  }\n  const definition = platformRegistry.getPlatform(provider.platform);\n  const settings = definition\n    ? mergeWithDefaults(definition.schema, provider.settings as Record<string, unknown> | undefined)\n    : ((provider.settings as Record<string, unknown>) ?? {});\n  return {\n    platform: provider.platform as MessagePlatformType,\n    service: createServiceForBot(provider),\n    settings,\n  };\n};\n\n/** Resolve a user-owned System Bot connection into a runnable service. */\nconst resolveMessengerInstall = async (\n  ctx: { serverDB: any; userId: string },","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/lobehub/lobehub/blob/10f24d7ade75139093a9373b364f6bc91f3cd7db/apps/server/src/routers/lambda/botMessage.ts#L129-L165","documentation":"Thrown by resolveBot when AgentBotProviderModel.findById(botId) returns null. The model is constructed userId-scoped with workspace context, so a bot owned by another user or in a different workspace is indistinguishable from a non-existent one. This fires before the enabled check and before service creation.","triggerScenarios":"Calling any botMessage procedure that takes a botId (sendMessage, readMessages, editMessage, etc.) with an id that does not exist or is not visible to the caller. The query returns null due to ownership scoping.","commonSituations":"Stale botId after the bot provider was deleted. Cross-user/cross-workspace botId. Typo or truncated id. Bot created in a different workspace than the caller's current context.","solutions":["Verify the botId exists via the bot provider list API for the current user/workspace.","Re-create or re-register the bot provider if it was deleted.","Ensure the caller's workspaceId matches where the bot was registered.","Check for typos or copy errors in the botId."],"exampleFix":"// before: botId from a deleted or foreign workspace\nawait botMessage.sendMessage.mutate({ botId: 'stale-id', channelId, content }); // -> NOT_FOUND\n\n// after: list and use a valid bot\nconst bots = await botProvider.list();\nawait botMessage.sendMessage.mutate({ botId: bots[0].id, channelId, content });","handlingStrategy":"validation","validationCode":"// Confirm the bot exists and is visible to the caller before sending\nconst bots = await botProviderRouter.list.query();\nif (!bots.some((b) => b.id === botId)) {\n  throw new Error('Bot not found in your scope; re-register or check workspace');\n}\nawait botMessageRouter.sendMessage.mutate({ botId, channelId, content });","typeGuard":"const isOwnedBot = (\n  bot: { id: string; userId?: string; workspaceId?: string } | undefined,\n  ctx: { userId: string; workspaceId?: string }\n): boolean => !!bot && (bot.userId === ctx.userId || bot.workspaceId === ctx.workspaceId);","tryCatchPattern":"try {\n  await botMessageRouter.sendMessage.mutate({ botId, channelId, content });\n} catch (e) {\n  if (e.shape?.data?.code === 'NOT_FOUND' && /Bot not found/.test(e.message)) {\n    // refresh the bot list and prompt re-selection\n  } else throw e;\n}","preventionTips":["In the UI, populate botId selectors from a freshly fetched bot list scoped to the current user/workspace.","Avoid persisting botId in long-lived client state without a validity refresh.","Handle NOT_FOUND gracefully by re-querying available bots."],"tags":["bot","not-found","ownership","workspace"],"backgroundTag":null,"analyzedSha":"10f24d7ade75139093a9373b364f6bc91f3cd7db","analyzedAt":"2026-08-12T11:43:19.543Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}