iflytek/astron-agent · warning · BusinessException
TOOLBOX_NO_COLLECT
TOOLBOX_NO_COLLECT
Error message
BusinessException(ResponseEnum.TOOLBOX_NO_COLLECT)
What it means
The favorite flow throws TOOLBOX_NO_COLLECT when favoriteFlag == 1 (unfavorite) but no existing UserFavoriteTool record is found for the user/tool (or MCP tool). Removing a favorite that does not exist is rejected. The code also maintains a Redis favorites set and prunes it when it becomes empty; this error fires in the else branch of that unfavorite path when there is nothing to remove.
Solutions
- Verify the tool is actually in the user's favorites before sending favoriteFlag=1.
- Treat the error as success when the desired end state (not favorited) already holds.
- Refresh the UI favorite state from the server so stale toggles aren't sent.
- Check the isMcp flag and toolId/mcpToolId pairing matches how the favorite was originally created.
Example fix
// before
favoriteService.setFavorite(userId, toolId, 1); // throws if not favorited
// after
if (userFavoriteToolMapper.findByUserIdAndToolId(userId, toolId).isPresent()) {
favoriteService.setFavorite(userId, toolId, 1);
} // else: already unfavorited, no-op
Defensive patterns
Strategy: validation
Validate before calling
boolean favorited = userFavoriteToolMapper.findByUserIdAndToolId(userId, toolId).isPresent();
if (favorited) { /* safe to send favoriteFlag=1 */ } Try / catch
try {
favoriteService.setFavorite(userId, toolId, 1);
} catch (BusinessException e) {
if ("TOOLBOX_NO_COLLECT".equals(e.getCode())) {
// already unfavorited; sync UI state to unfavorited
}
} Prevention
- Refresh favorite state from the server before toggling off.
- Keep the Redis favorites cache consistent with DB rows to avoid stale UI states.
- Match the isMcp flag and id fields exactly as used when the favorite was created.
When it happens
Trigger: Calling unfavorite (favoriteFlag=1) for a tool the user never favorited; double unfavorite after the first already removed the row; stale UI showing a favorited state that was cleared in another session; mismatch between the DB favorite row and the Redis cache key (isMcp flag differences).
Common situations: Favorite toggled off in another tab then toggled off again; Redis favorites cache deleted/expired while UI still shows favorited; clients sending unfavorite for MCP tool with wrong toolId/mcpToolId mapping.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- TOOLBOX_ALREADY_COLLECT
- BOT_CHAIN_SUBMIT_ERROR
- WeChat official account record not found for unbinding…
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/37201b301a81bbef.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/tool/ToolBoxService.java:1267
}
userFavorite.setCreatedTime(new Timestamp(System.currentTimeMillis()));
// 1-indicates favorite
userFavorite.setUseFlag(1);
userFavoriteToolMapper.save(userFavorite);
redisTemplate.opsForSet().add(redisKey, toolId);
} else if (favoriteFlag == 1) {
if (existingFavorite.isPresent()) {
UserFavoriteTool userFavorite = existingFavorite.get();
userFavorite.setDeleted(true);
userFavoriteToolMapper.updateFavoriteStatus(userFavorite);
redisTemplate.opsForSet().remove(redisKey, toolId);
// Check if collection is empty
Set<Object> favorites = redisTemplate.opsForSet().members(redisKey);
if (favorites == null || favorites.isEmpty()) {
redisTemplate.delete(redisKey);
}
} else {
throw new BusinessException(ResponseEnum.TOOLBOX_NO_COLLECT);
}
}
return result.get();
}
@Deprecated
public JSONObject extractToolRunHeader(JSONObject reqData) {
JSONObject jsonObject = new JSONObject();
JSONArray toolHttpHeaders = reqData.getJSONArray("toolHttpHeaders");
if (toolHttpHeaders != null && !toolHttpHeaders.isEmpty()) {
List<WebSchemaItem> items = toolHttpHeaders.toJavaList(WebSchemaItem.class);
JSONObject obj = recurGenRunParam(items);
jsonObject.putAll(obj);
}
return jsonObject;
}
View on GitHub (pinned to 5e758547a8)