{"record":{"id":"320d9cf6d275cbd5","repo":"qiurunze123/miaosha","slug":"30005","errorCode":"30005","errorMessage":"Session不存在或者已经失效!","messagePattern":"Session不存在或者已经失效!","errorType":"exception","errorClass":"GlobleException","httpStatus":null,"severity":"error","filePath":"miaosha-v2/miaosha-web/src/main/java/com/geekq/miaosha/controller/GoodsController.java","lineNumber":91,"sourceCode":"    @RequestMapping(value = \"/to_detail2/{goodsId}\", produces = \"text/html\")\n    @ResponseBody\n    public String detail2(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user,\n                          @PathVariable(\"goodsId\") long goodsId) {\n        model.addAttribute(\"user\", user);\n\n        //取缓存\n        String html = redisService.get(GoodsKey.getGoodsDetail, \"\" + goodsId, String.class);\n        if (!StringUtils.isEmpty(html)) {\n            return html;\n        }\n        //手动渲染\n        GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);\n        /**\n         * rpc服务化接口\n         */\n        ResultGeekQOrder<GoodsVoOrder> goodsVoOrderResultGeekQOrder = goodsServiceRpc.getGoodsVoByGoodsId(goodsId);\n        if (!AbstractResultOrder.isSuccess(goodsVoOrderResultGeekQOrder)) {\n            throw new GlobleException(ResultStatus.SESSION_ERROR);\n        }\n        model.addAttribute(\"goods\", goods);\n\n        long startAt = goods.getStartDate().getTime();\n        long endAt = goods.getEndDate().getTime();\n        long now = System.currentTimeMillis();\n\n        int miaoshaStatus = 0;\n        int remainSeconds = 0;\n        if (now < startAt) {//秒杀还没开始，倒计时\n            miaoshaStatus = 0;\n            remainSeconds = (int) ((startAt - now) / 1000);\n        } else if (now > endAt) {//秒杀已经结束\n            miaoshaStatus = 2;\n            remainSeconds = -1;\n        } else {//秒杀进行中\n            miaoshaStatus = 1;\n            remainSeconds = 0;","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/qiurunze123/miaosha/blob/e58017658e549b63fc4db2160d2325ccd7f8435b/miaosha-v2/miaosha-web/src/main/java/com/geekq/miaosha/controller/GoodsController.java#L73-L109","documentation":"Thrown by GoodsController.detail2() (miaosha-v2) when the RPC call goodsServiceRpc.getGoodsVoByGoodsId(goodsId) returns a non-success result. Maps to ResultStatus.SESSION_ERROR (code 30005, 'Session不存在或者已经失效!'). This is a MISLABELED error: the failure is an RPC/data-fetch problem, not a session problem. The SESSION_ERROR code is misleading — it will confuse the front-end and debugging because it implies the user's session expired when in fact the goods provider failed. The provider's GoodsServiceImpl catches DB exceptions and returns ORDER_GET_FAIL (code 40004); the mock returns null which also triggers this path.","triggerScenarios":"GET /goods/to_detail2/{goodsId} when goodsServiceRpc.getGoodsVoByGoodsId() fails — provider DB error, provider down, or mock returning null. Note that detail2() also calls the local goodsService.getGoodsVoByGoodsId() at line 85 before the RPC check, so the local call may succeed while the RPC fails, leading to inconsistent behavior.","commonSituations":"miaosha-order-provider is down or deregistered from Dubbo; provider DB is unreachable; GoodsServiceMock is active (getGoodsVoByGoodsId returns null); provider times out; the goodsId does not exist in the provider's goods table (mapper returns null, which is set as data but status may not be SUCCESS depending on build()).","solutions":["Replace ResultStatus.SESSION_ERROR with ResultStatus.SYSTEM_ERROR or a dedicated RPC error code to accurately reflect the failure cause.","Verify miaosha-order-provider is running and registered in the service registry.","Check provider logs for '获取单个订单失败' to find the underlying exception.","Remove the redundant local goodsService.getGoodsVoByGoodsId() call (line 85) since the RPC result is what matters, or use the local result consistently.","If the mock is active, fix GoodsServiceMock.getGoodsVoByGoodsId() to return a valid ResultGeekQOrder instead of null."],"exampleFix":"// before\nResultGeekQOrder<GoodsVoOrder> goodsVoOrderResultGeekQOrder = goodsServiceRpc.getGoodsVoByGoodsId(goodsId);\nif (!AbstractResultOrder.isSuccess(goodsVoOrderResultGeekQOrder)) {\n    throw new GlobleException(ResultStatus.SESSION_ERROR);\n}\n\n// after — use the correct error code for an RPC failure\nResultGeekQOrder<GoodsVoOrder> goodsVoOrderResultGeekQOrder = goodsServiceRpc.getGoodsVoByGoodsId(goodsId);\nif (!AbstractResultOrder.isSuccess(goodsVoOrderResultGeekQOrder)) {\n    throw new GlobleException(ResultStatus.SYSTEM_ERROR);\n}","handlingStrategy":"fallback","validationCode":"// Use the local goodsService result that was already fetched at line 85\nGoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);\nResultGeekQOrder<GoodsVoOrder> rpcResult = goodsServiceRpc.getGoodsVoByGoodsId(goodsId);\nif (!AbstractResultOrder.isSuccess(rpcResult)) {\n    // Fall back to local result instead of throwing SESSION_ERROR\n    if (goods == null) {\n        throw new GlobleException(ResultStatus.SYSTEM_ERROR);\n    }\n    // proceed with local goods data\n}","typeGuard":"// Validate RPC result before consuming\nif (goodsVoOrderResultGeekQOrder != null\n    && goodsVoOrderResultGeekQOrder.getStatus() == ResultStatusOrder.SUCCESS\n    && goodsVoOrderResultGeekQOrder.getData() != null) {\n    // safe to use goodsVoOrderResultGeekQOrder.getData()\n}","tryCatchPattern":"try {\n    ResultGeekQOrder<GoodsVoOrder> rpcResult = goodsServiceRpc.getGoodsVoByGoodsId(goodsId);\n    if (!AbstractResultOrder.isSuccess(rpcResult)) {\n        log.error(\"Goods RPC failed for goodsId={}\", goodsId);\n        throw new GlobleException(ResultStatus.SYSTEM_ERROR);\n    }\n} catch (GlobleException e) {\n    // Do NOT treat as session error — it is an RPC failure\n    throw e;\n}","preventionTips":["Fix the mislabeled SESSION_ERROR — use SYSTEM_ERROR or a dedicated RPC error code.","Ensure miaosha-order-provider is registered and healthy in the Dubbo registry.","Fix GoodsServiceMock.getGoodsVoByGoodsId() to return a valid ResultGeekQOrder instead of null.","Add monitoring/alerting on provider-side '获取单个订单失败' log entries.","Consider using the already-fetched local goodsService result as a fallback instead of throwing."],"tags":["rpc","dubbo","goods","mislabeled-error","dependency-unavailable","miaosha-v2"],"backgroundTag":null,"analyzedSha":"e58017658e549b63fc4db2160d2325ccd7f8435b","analyzedAt":"2026-08-14T05:22:03.691Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}