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

  1. Verify the tool is actually in the user's favorites before sending favoriteFlag=1.
  2. Treat the error as success when the desired end state (not favorited) already holds.
  3. Refresh the UI favorite state from the server so stale toggles aren't sent.
  4. 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

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


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)