{"record":{"id":"37201b301a81bbef","repo":"iflytek/astron-agent","slug":"toolbox-no-collect","errorCode":"TOOLBOX_NO_COLLECT","errorMessage":"BusinessException(ResponseEnum.TOOLBOX_NO_COLLECT)","messagePattern":"BusinessException\\(ResponseEnum\\.TOOLBOX_NO_COLLECT\\)","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"warning","filePath":"console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/tool/ToolBoxService.java","lineNumber":1267,"sourceCode":"            }\n            userFavorite.setCreatedTime(new Timestamp(System.currentTimeMillis()));\n            // 1-indicates favorite\n            userFavorite.setUseFlag(1);\n            userFavoriteToolMapper.save(userFavorite);\n            redisTemplate.opsForSet().add(redisKey, toolId);\n        } else if (favoriteFlag == 1) {\n            if (existingFavorite.isPresent()) {\n                UserFavoriteTool userFavorite = existingFavorite.get();\n                userFavorite.setDeleted(true);\n                userFavoriteToolMapper.updateFavoriteStatus(userFavorite);\n                redisTemplate.opsForSet().remove(redisKey, toolId);\n                // Check if collection is empty\n                Set<Object> favorites = redisTemplate.opsForSet().members(redisKey);\n                if (favorites == null || favorites.isEmpty()) {\n                    redisTemplate.delete(redisKey);\n                }\n            } else {\n                throw new BusinessException(ResponseEnum.TOOLBOX_NO_COLLECT);\n            }\n        }\n        return result.get();\n    }\n\n\n    @Deprecated\n    public JSONObject extractToolRunHeader(JSONObject reqData) {\n        JSONObject jsonObject = new JSONObject();\n        JSONArray toolHttpHeaders = reqData.getJSONArray(\"toolHttpHeaders\");\n        if (toolHttpHeaders != null && !toolHttpHeaders.isEmpty()) {\n            List<WebSchemaItem> items = toolHttpHeaders.toJavaList(WebSchemaItem.class);\n            JSONObject obj = recurGenRunParam(items);\n            jsonObject.putAll(obj);\n        }\n        return jsonObject;\n    }\n","sourceCodeStart":1249,"sourceCodeEnd":1285,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/tool/ToolBoxService.java#L1249-L1285","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nfavoriteService.setFavorite(userId, toolId, 1); // throws if not favorited\n// after\nif (userFavoriteToolMapper.findByUserIdAndToolId(userId, toolId).isPresent()) {\n    favoriteService.setFavorite(userId, toolId, 1);\n} // else: already unfavorited, no-op\n","handlingStrategy":"validation","validationCode":"boolean favorited = userFavoriteToolMapper.findByUserIdAndToolId(userId, toolId).isPresent();\nif (favorited) { /* safe to send favoriteFlag=1 */ }","typeGuard":null,"tryCatchPattern":"try {\n    favoriteService.setFavorite(userId, toolId, 1);\n} catch (BusinessException e) {\n    if (\"TOOLBOX_NO_COLLECT\".equals(e.getCode())) {\n        // already unfavorited; sync UI state to unfavorited\n    }\n}","preventionTips":["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."],"tags":["favorites","missing-record","idempotency"],"backgroundTag":"invalid-state-transition","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}