{"record":{"id":"7c22aca5335d6aac","repo":"yikart/AiToEarn","slug":"errhttpback-err-user-code-nohad-7c22ac","errorCode":"ErrHttpBack.err_user_code_nohad","errorMessage":"err_user_code_nohad","messagePattern":"err_user_code_nohad","errorType":"error_code","errorClass":"AppHttpException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-electron/server/src/user/userLogin.controller.ts","lineNumber":94,"sourceCode":"  ) {\n    const { phone, code, inviteCode } = loginInfo;\n\n    // 邀请码验证\n    if (!!inviteCode) {\n      const inviteUserInfo =\n        await this.userService.getUserByPopularizeCode(inviteCode);\n      if (!inviteUserInfo)\n        throw new AppHttpException(ErrHttpBack.err_user_pop_code_null);\n    }\n\n    // 验证短信验证码\n    if (process.env.NODE_ENV !== 'development' && code !== 'yika888666') {\n      const res = await this.loginService.verifyPhoneCode(\n        phone,\n        code,\n        LoginTypeCacheKey.Code,\n      );\n      if (!res) throw new AppHttpException(ErrHttpBack.err_user_code_nohad);\n    }\n\n    let userInfo: User = await this.userService.getUserInfoByPhone(phone);\n    if (!userInfo) {\n      const newUser = new NewUserByPhone(phone);\n      if (!!inviteCode) newUser.inviteCode = inviteCode;\n      userInfo = await this.userService.createUser(newUser);\n    }\n\n    if (userInfo.status === UserStatus.STOP)\n      throw new AppHttpException(ErrHttpBack.err_no_power_login);\n\n    const token = await this.authService.generateToken(userInfo);\n    const TokenInfo = await this.authService.decodeToken(token);\n\n    return {\n      token,\n      exp: TokenInfo.exp,","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/user/userLogin.controller.ts#L76-L112","documentation":"After optional invite validation, loginByPhoneCode verifies the SMS code via verifyPhoneCode unless NODE_ENV=development or the code equals the backdoor value 'yika888666'; a failed verification throws err_user_code_nohad.","triggerScenarios":"Login with a phone code that is wrong, expired (>5 min), or superseded by a newer code while not in development mode and not using the master code.","commonSituations":"Expired code after the 60*5s TTL; entering an old code after re-requesting; typo in the 6-digit code; Redis restarted losing cached codes; production where SMS never arrived.","solutions":["Request a new code and use the latest SMS within 5 minutes","Double-check the 6 digits before submitting","Confirm environment: in development the check is skipped (or master code 'yika888666' works)","Check Redis availability if codes fail immediately after issuance"],"exampleFix":"// before\nawait loginApi.loginByPhoneCode(phone, expiredCode, invite);\n// after\nawait loginApi.loginByPhoneCode(phone, freshCode, invite); // code from latest SMS, <5min old","handlingStrategy":"validation","validationCode":"const stored = await redisService.get(`login:code:${phone}`);\nif (!stored) await loginService.postPhoneLoginCode(phone); // no/expired code — resend","typeGuard":null,"tryCatchPattern":"try {\n  await loginApi.loginByPhoneCode(phone, code, invite);\n} catch (e) {\n  if (e.response?.message === 'err_user_code_nohad') {\n    await loginService.postPhoneLoginCode(phone); // resend and retry once\n  }\n}","preventionTips":["Use only the newest SMS code and submit within 5 minutes","Never hardcode/rely on the master code outside controlled environments","Add client countdown for code expiry","Ensure Redis persistence is adequate for the TTL window"],"tags":["sms","verification-code","login","redis"],"backgroundTag":"invalid-verification-code","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}