{"record":{"id":"1a04ce4d252e29d5","repo":"jackwener/OpenCLI","slug":"d-msg-api-failed","errorCode":null,"errorMessage":"${d.msg || 'API failed'}","messagePattern":"\\$\\{d\\.msg \\|\\| 'API failed'\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"clis/nowcoder/notifications.js","lineNumber":16,"sourceCode":"import { cli } from '@jackwener/opencli/registry';\n\ncli({\n    site: 'nowcoder',\n    name: 'notifications',\n    access: 'read',\n    description: 'Unread message summary',\n    domain: 'www.nowcoder.com',\n    args: [],\n    columns: ['type', 'unread'],\n    pipeline: [\n        { navigate: 'https://www.nowcoder.com' },\n        { evaluate: `(async () => {\n  const r = await fetch('https://gw-c.nowcoder.com/api/sparta/message/pc/unread/detail', {credentials: 'include'});\n  const d = await r.json();\n  if (!d.success) throw new Error(d.msg || 'API failed');\n  const data = d.data;\n  return [\n    {type: 'system', unread: data.systemNotice?.unreadCount || 0},\n    {type: 'likes', unread: data.likeCollect?.unreadCount || 0},\n    {type: 'comments', unread: data.commentMessage?.unreadCount || 0},\n    {type: 'follows', unread: data.followMessage?.unreadCount || 0},\n    {type: 'messages', unread: data.privateMessage?.unreadCount || 0},\n    {type: 'job_apply', unread: data.nowPickJobApply?.unreadCount || 0},\n    {type: 'total', unread: data.total?.unreadCount || 0},\n  ];\n})()\n` },\n    ],\n});\n","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/nowcoder/notifications.js#L1-L31","documentation":"The notifications pipeline fetches https://gw-c.nowcoder.com/api/sparta/message/pc/unread/detail in-page and throws new Error(d.msg || 'API failed') when the response JSON has success falsy. The resulting CommandExecutionError carries the server-provided msg (or the generic 'API failed'). It means nowcoder's gateway accepted the request but rejected it — usually due to missing/invalid session credentials or an API-level error.","triggerScenarios":"Calling the nowcoder notifications command while logged out (API returns success:false with auth msg); rate limiting or server-side validation errors returning success:false; API contract change making data absent.","commonSituations":"Expired `t` cookie so gateway denies the unread-detail call; calling from an IP nowcoder distrusts; nowcoder API returning an error message after a backend change.","solutions":["Re-authenticate with `nowcoder login` so the request includes a valid session","Read d.msg in the error for the server's specific reason","Retry later if msg indicates rate limiting or server trouble","If success:false with no msg persists, verify the endpoint URL is still valid"],"exampleFix":"// before\nconst unread = await runNowcoderNotifications();\n// after\ntry {\n  const unread = await runNowcoderNotifications();\n} catch (e) {\n  if (/API failed|nowcoder/.test(e.message)) {\n    await runNowcoderLogin();\n    return runNowcoderNotifications();\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"const cookies = await page.getCookies({ url: 'https://www.nowcoder.com' });\nif (!cookies.some(c => c.name === 't' && c.value)) {\n  throw new Error('Login to nowcoder before fetching notifications');\n}","typeGuard":"function isApiSuccess(d) {\n  return !!d && d.success === true && typeof d.data === 'object' && d.data !== null;\n}","tryCatchPattern":"try {\n  return await nowcoderNotifications();\n} catch (e) {\n  if (/API failed|nowcoder/i.test(e.message)) {\n    await nowcoderLogin();\n    return nowcoderNotifications();\n  }\n  throw e;\n}","preventionTips":["Always authenticate before querying unread-message APIs","Surface d.msg from responses rather than swallowing it","Rate-limit repeated notification polls","Handle success:false explicitly in your own in-page fetch pipelines"],"tags":["api-error","auth","network","nowcoder"],"backgroundTag":"api-success-false","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}