{"record":{"id":"d320a20a6d5f6c95","repo":"YMFE/yapi","slug":"token","errorCode":null,"errorMessage":"token 不能为空","messagePattern":"token 不能为空","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/utils/token.js","lineNumber":45,"sourceCode":"   第二个参数用于指定解密时所使用的密码，其参数值为一个二进制格式的字符串或一个Buffer对象，该密码同样必须与加密该数据时所使用的密码保持一致\n  */\n  const decipher = crypto.createDecipher('aes192', password);\n\n  /*\n   第一个参数为一个Buffer对象或一个字符串，用于指定需要被解密的数据\n   第二个参数用于指定被解密数据所使用的编码格式，可指定的参数值为 'hex', 'binary', 'base64'等，\n   第三个参数用于指定输出解密数据时使用的编码格式，可选参数值为 'utf-8', 'ascii' 或 'binary';\n  */\n  let decrypted = decipher.update(data, 'hex', 'utf-8');\n\n  decrypted += decipher.final('utf-8');\n  return decrypted;\n}; \n\nconst defaultSalt = 'abcde';\n\nexports.getToken = function getToken(token, uid){\n  if(!token)throw new Error('token 不能为空')\n  yapi.WEBCONFIG.passsalt = yapi.WEBCONFIG.passsalt || defaultSalt;\n  return aseEncode(uid + '|' + token, yapi.WEBCONFIG.passsalt)\n}\n\nexports.parseToken = function parseToken(token){\n  if(!token)throw new Error('token 不能为空')\n  yapi.WEBCONFIG.passsalt = yapi.WEBCONFIG.passsalt || defaultSalt;\n  let tokens;\n  try{\n    tokens = aseDecode(token, yapi.WEBCONFIG.passsalt)\n  }catch(e){}  \n  if(tokens && typeof tokens === 'string' && tokens.indexOf('|') > 0){\n    tokens = tokens.split('|')\n    return {\n      uid: tokens[0],\n      projectToken: tokens[1]\n    }\n  }","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/YMFE/yapi/blob/59bade3a8a43e7db077d38a4b0c7c584f30ddf8c/server/utils/token.js#L27-L63","documentation":"getToken() in server/utils/token.js throws this when called with a falsy token. The function encodes `uid|token` with AES-like aseEncode and requires a non-empty token to build a credential.","triggerScenarios":"Calling yapi.commons.getToken('', uid), getToken(null, uid), or getToken(undefined, uid); typically a login/OpenAPI flow where the token field was never populated.","commonSituations":"A project token was deleted or never created; DB lookup returned null/undefined; request body omitted the token field; migration left token column empty.","solutions":["Ensure the caller fetches a valid project token from the `token` collection (e.g. project.token or token table) before calling getToken","Validate the token value is a non-empty string before calling getToken","Fix upstream code that passes the result of a failed lookup (null/undefined) directly into getToken"],"exampleFix":"// before\nconst t = await tokenModel.get(projectId, 'interface');\nconst tokenStr = yapi.commons.getToken(t, uid);\n// after\nconst t = await tokenModel.get(projectId, 'interface');\nif (!t) throw new Error('project token not found, generate one in project settings');\nconst tokenStr = yapi.commons.getToken(t, uid);","handlingStrategy":"validation","validationCode":"function safeGetToken(token, uid){ if (typeof token !== 'string' || token.length === 0) throw new TypeError('getToken requires a non-empty token string'); return yapi.commons.getToken(token, uid); }","typeGuard":"function isNonEmptyString(v){ return typeof v === 'string' && v.length > 0; }","tryCatchPattern":"try {\n  const t = yapi.commons.getToken(token, uid);\n} catch (e) {\n  if (e.message === 'token 不能为空') { /* prompt user to generate a project token */ }\n  else throw e;\n}","preventionTips":["Always fetch the token from the project's token record and check it exists before encoding","Never pass raw DB query results directly into getToken without a null check","Surface a clear 'generate token first' message in the UI when no token exists"],"tags":["token","validation","missing-argument"],"backgroundTag":"missing-required-token","analyzedSha":"59bade3a8a43e7db077d38a4b0c7c584f30ddf8c","analyzedAt":"2026-08-29T08:45:22.203Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}