{"record":{"id":"3224e91219eec110","repo":"lyswhut/lx-music-desktop","slug":"error-3224e9","errorCode":null,"errorMessage":"获取回复评论失败","messagePattern":"获取回复评论失败","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/utils/musicSdk/mg/comment.js","lineNumber":68,"sourceCode":"    })\n    const { body, statusCode } = await _requestObj2.promise\n    // console.log(body)\n    if (statusCode != 200 || body.code !== '000000') throw new Error('获取热门评论失败')\n    const total = parseInt(body.data.cfgHotCount)\n    return { source: 'mg', comments: this.filterComment(body.data.hotComments), total, page, limit, maxPage: Math.ceil(total / limit) || 1 }\n  },\n  async getReplyComment(musicInfo, replyId, page = 1, limit = 10) {\n    if (this._requestObj2) this._requestObj2.cancelHttp()\n\n    // const _requestObj2 = httpFetch(`https://music.migu.cn/v3/api/comment/listCommentsById?commentId=${replyId}&pageSize=${limit}&pageNo=${page}`, {\n    const _requestObj2 = httpFetch(`https://app.c.nf.migu.cn/MIGUM3.0/user/comment/stack/${replyId}/v1.0?pageSize=${limit}&queryType=2&resourceId=${musicInfo.songId}&resourceType=2&start=${(page - 1) * limit}`, {\n      headers: {\n        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',\n      },\n    })\n    const { body, statusCode } = await _requestObj2.promise\n    // console.log(body)\n    if (statusCode != 200 || body.code !== '000000') throw new Error('获取回复评论失败')\n    const total = parseInt(body.data.replyTotalCount)\n    return { source: 'mg', comments: this.filterComment(body.data.mainCommentItem.replyComments), total, page, limit, maxPage: Math.ceil(total / limit) || 1 }\n  },\n  filterComment(rawList) {\n    return rawList.map(item => ({\n      id: item.commentId,\n      text: item.commentInfo,\n      time: item.commentTime,\n      timeStr: dateFormat2(new Date(item.commentTime).getTime()),\n      userName: item.user.nickName,\n      avatar: item.user.middleIcon || item.user.bigIcon || item.user.smallIcon,\n      userId: item.user.userId,\n      likedCount: item.opNumItem.thumbNum,\n      replyNum: item.replyTotalCount,\n      reply: item.replyComments.map(c => ({\n        id: c.replyId,\n        text: c.replyInfo,\n        time: c.replyTime,","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/lyswhut/lx-music-desktop/blob/9c364b482e5621a1d38b50e8610d2fb974457e6e/src/renderer/utils/musicSdk/mg/comment.js#L50-L86","documentation":"Thrown by Migu's getReplyComment when the reply-thread endpoint at https://app.c.nf.migu.cn/MIGUM3.0/user/comment/stack/{replyId}/v1.0 returns non-200 or body.code !== '000000'. Reads body.data.replyTotalCount and body.data.mainCommentItem.replyComments. Critically, this method reuses _requestObj2 (same field as getHotComment), so calling getReplyComment cancels any in-flight getHotComment and vice versa — a shared-request-object bug.","triggerScenarios":"Calling getReplyComment(musicInfo, replyId, page, limit) with an invalid or deleted replyId. The parent comment was removed so the thread no longer exists. Concurrent calls to getReplyComment and getHotComment cancel each other via the shared _requestObj2.cancelHttp().","commonSituations":"User expands a reply thread for a comment that was deleted between fetching the comment list and expanding replies. Rapid navigation between hot comments and reply threads triggers mutual cancellation via the shared _requestObj2.","solutions":["Log body.code and statusCode before throwing to diagnose.","Give getReplyComment its own _requestObj3 (already declared as null on line 8 but unused) instead of reusing _requestObj2.","Validate replyId is a non-empty string before calling.","Catch in the caller and show 'replies unavailable' for deleted threads."],"exampleFix":"// before — getReplyComment reuses _requestObj2, conflicting with getHotComment\nasync getReplyComment(musicInfo, replyId, page = 1, limit = 10) {\n  if (this._requestObj2) this._requestObj2.cancelHttp()\n  const _requestObj2 = httpFetch(...)\n  ...\n  if (statusCode != 200 || body.code !== '000000') throw new Error('获取回复评论失败')\n}\n\n// after — use the declared-but-unused _requestObj3\nasync getReplyComment(musicInfo, replyId, page = 1, limit = 10) {\n  if (this._requestObj3) this._requestObj3.cancelHttp()\n  const _requestObj3 = httpFetch(...)\n  this._requestObj3 = _requestObj3\n  ...\n  if (statusCode != 200 || !body || body.code !== '000000') {\n    console.warn('mg getReplyComment failed', { statusCode, code: body?.code })\n    throw new Error('获取回复评论失败')\n  }\n}","handlingStrategy":"try-catch","validationCode":"function isValidReplyRequest(musicInfo, replyId) {\n  return !!musicInfo.songId && typeof replyId === 'string' && replyId.length > 0\n}","typeGuard":"function isMiguReplyResponse(body) {\n  return body != null && typeof body === 'object' && body.code === '000000' && body.data != null && body.data.mainCommentItem != null\n}","tryCatchPattern":"try {\n  const result = await mgComment.getReplyComment(musicInfo, replyId, page, limit)\n} catch (err) {\n  if (err.message === '获取回复评论失败') {\n    console.warn('Migu reply comments failed for reply', replyId)\n    return { source: 'mg', comments: [], total: 0, page, limit, maxPage: 1 }\n  }\n  throw err\n}","preventionTips":["Give getReplyComment its own request object (_requestObj3 is declared but unused) instead of reusing _requestObj2 to avoid cancelling in-flight getHotComment calls.","Validate replyId is a non-empty string before calling.","Catch the error and show 'replies unavailable' for deleted comment threads.","Avoid concurrent getHotComment and getReplyComment calls due to the shared _requestObj2."],"tags":["migu","reply-comments","network","api-contract","shared-state-bug","https"],"backgroundTag":null,"analyzedSha":"9c364b482e5621a1d38b50e8610d2fb974457e6e","analyzedAt":"2026-08-12T15:14:48.244Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}