iflytek/astron-agent · error · BusinessException
BOT_CHAIN_SUBMIT_ERROR
BOT_CHAIN_SUBMIT_ERROR
Error message
BOT_CHAIN_SUBMIT_ERROR
What it means
BusinessException with code BOT_CHAIN_SUBMIT_ERROR thrown by chatWorkflowBot when userLangChainDataService.findOneByBotId(botId) returns null — i.e. no workflow (LangChain) binding exists for the bot, so there is no flowId to submit the chat request to.
Solutions
- Verify the botId is correct and that the bot is actually a workflow-type bot.
- Re-fetch the bot list to clear stale botIds and retry with a valid one.
- Re-publish/bind the workflow to the bot so a UserLangChainInfo record with a flowId exists.
- Check the database for a missing user_lang_chain_info row for this botId and restore the binding if it was lost.
Example fix
// before: chat with any bot id
await chatWorkflowBot({ botId: someId, ask });
// after: only workflow bots support this endpoint
const bot = await getBot(someId);
if (!bot || bot.type !== 'workflow') throw new Error('Bot has no workflow bound');
await chatWorkflowBot({ botId: someId, ask }); Defensive patterns
Strategy: validation
Validate before calling
const bot = await getBot(botId);
if (!bot || !bot.flowId) throw new Error('Bot has no workflow binding; cannot chat'); Type guard
function isWorkflowBot(bot) { return bot != null && typeof bot.flowId === 'string' && bot.flowId.length > 0; } Try / catch
try { await chatWorkflowBot({ botId, ask }); } catch (e) { if (e.code === 'BOT_CHAIN_SUBMIT_ERROR') { await refreshBotList(); notify('This bot has no workflow bound'); } else throw e; } Prevention
- Only call the workflow chat endpoint for workflow-type bots
- Refresh cached botIds after bot deletion or conversion
- Ensure copy/import flows also copy the workflow binding
- Validate flowId exists before submitting chat
When it happens
Trigger: Sending a chat request to a botId that has no associated workflow record: the bot was created as a basic bot, the workflow binding was deleted, the wrong botId was passed, or the binding row is missing/corrupt in the database.
Common situations: Client caching a stale botId after the bot was deleted or converted; bots imported/copied without their workflow binding; race between bot deletion and an in-flight chat request; environment mismatch where the bot exists in one DB but its chain record is in another.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/cae00e683b727480.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/commons/src/main/java/com/iflytek/astron/console/commons/service/workflow/impl/WorkflowBotChatServiceImpl.java:124
public void chatWorkflowBot(ChatBotReqDto chatBotReqDto, SseEmitter sseEmitter, String sseId, String workflowOperation, String workflowVersion) {
String uid = chatBotReqDto.getUid();
Long chatId = chatBotReqDto.getChatId();
String ask = chatBotReqDto.getAsk();
String url = chatBotReqDto.getUrl();
Integer botId = chatBotReqDto.getBotId();
if (StrUtil.isBlank(ask)) {
log.warn("Rejecting workflow chat request with empty user input, uid: {}, chatId: {}, botId: {}",
uid, chatId, botId);
throw new BusinessException(ResponseEnum.PARAMETER_ERROR);
}
JSONObject inputs = new JSONObject();
inputs.put("AGENT_USER_INPUT", ask);
UserLangChainInfo userLangChainInfo = userLangChainDataService.findOneByBotId(botId);
if (userLangChainInfo == null) {
throw new BusinessException(ResponseEnum.BOT_CHAIN_SUBMIT_ERROR);
}
String flowId = userLangChainInfo.getFlowId();
String effectiveWorkflowVersion = resolveWorkflowVersion(botId, flowId, workflowVersion);
// Record current question
ChatReqRecords chatReqRecords = new ChatReqRecords();
chatReqRecords.setChatId(chatId);
chatReqRecords.setUid(uid);
chatReqRecords.setMessage(ask);
chatReqRecords.setClientType(0);
chatReqRecords.setCreateTime(LocalDateTime.now());
chatReqRecords.setUpdateTime(LocalDateTime.now());
chatReqRecords.setNewContext(1);
chatReqRecords = chatDataService.createRequest(chatReqRecords);
Long reqId = chatReqRecords.getId();
JSONObject extraInputs = JSONObject.parseObject(userLangChainInfo.getExtraInputs());
// Handle multi-file parameter typeView on GitHub (pinned to 5e758547a8)