{"record":{"id":"8dcf33b2d6f2a9d7","repo":"YMFE/yapi","slug":"action-payload-data-errmsg","errorCode":null,"errorMessage":"action.payload.data.errmsg","messagePattern":"action\\.payload\\.data\\.errmsg","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/reducer/middleware/messageMiddleware.js","lineNumber":16,"sourceCode":"import { message } from 'antd';\n\nexport default () => next => action => {\n  if (!action) {\n    return;\n  }\n  if (action.error) {\n    message.error((action.payload && action.payload.message) || '服务器错误');\n  } else if (\n    action.payload &&\n    action.payload.data &&\n    action.payload.data.errcode &&\n    action.payload.data.errcode !== 40011\n  ) {\n    message.error(action.payload.data.errmsg);\n    throw new Error(action.payload.data.errmsg);\n  }\n  return next(action);\n};\n","sourceCodeStart":1,"sourceCodeEnd":20,"githubUrl":"https://github.com/YMFE/yapi/blob/59bade3a8a43e7db077d38a4b0c7c584f30ddf8c/client/reducer/middleware/messageMiddleware.js#L1-L20","documentation":"This message middleware inspects every action carrying an HTTP response payload; when the backend returns a non-zero errcode other than 40011 (a whitelisted code), it surfaces errcode/errmsg as a message toast and throws so reducers skip processing the failed response. It is the central funnel for backend business errors reaching the frontend.","triggerScenarios":"Any axios-dispatched action whose response body has data.errcode truthy and !== 40011, e.g. an expired login token, insufficient permissions, or invalid params returned by a YApi API endpoint.","commonSituations":"Session expired (errcode 40011 handled elsewhere), hitting an API without login, plugin/backend returning business errors, backend exceptions serialized into errcode/errmsg.","solutions":["Log in again or refresh the auth token, since most errcodes stem from expired/invalid sessions","Check the errmsg string to identify the backend rule violated (permissions, params, etc.)","Verify the request payload matches what the backend endpoint expects","If the error should not toast, add the errcode to the whitelist condition in messageMiddleware.js"],"exampleFix":"// before: raw request without token handling\nconst res = await axios.get('/api/project/get?id=1');\n// after: refresh token on auth errcodes\nif (res.data.errcode === 40011) { await refreshToken(); retry(); }\nelse if (res.data.errcode) { toast(res.data.errmsg); }","handlingStrategy":"try-catch","validationCode":"function hasBizError(action){ return !!(action.payload && action.payload.data && action.payload.data.errcode && action.payload.data.errcode !== 40011); }","typeGuard":"function isApiPayload(p){ return p && typeof p === 'object' && p.data && typeof p.data.errcode === 'number'; }","tryCatchPattern":"try {\n  const res = await dispatch(fetchProject(id));\n} catch (e) {\n  Message.error(e.message || '请求失败');\n}","preventionTips":["Always dispatch requests through the message middleware so errcodes surface uniformly","Handle errcode 40011 (token expiry) with re-login logic","Log errcode alongside errmsg when reporting issues","Validate request params client-side before calling APIs"],"tags":["http","frontend","redux-middleware","api-error"],"backgroundTag":"api-error-response","analyzedSha":"59bade3a8a43e7db077d38a4b0c7c584f30ddf8c","analyzedAt":"2026-08-29T08:45:22.203Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}