{"record":{"id":"2af7e2223512c150","repo":"yikart/AiToEarn","slug":"errhttpback-err-user-pop-code-null","errorCode":"ErrHttpBack.err_user_pop_code_null","errorMessage":"err_user_pop_code_null","messagePattern":"err_user_pop_code_null","errorType":"error_code","errorClass":"AppHttpException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-electron/server/src/user/userLogin.controller.ts","lineNumber":84,"sourceCode":"  }\n\n  @ApiOperation({\n    description: '手机号验证码登录',\n    summary: '手机号验证码登录',\n  })\n  @Public()\n  @Post('login/code/phone')\n  async loginByPhoneCode(\n    @Body(new ParamsValidationPipe()) loginInfo: PhoneLoginByCodeDto,\n  ) {\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    }","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/user/userLogin.controller.ts#L66-L102","documentation":"loginByPhoneCode accepts an optional inviteCode; if provided, it looks up the inviter by popularize code, and err_user_pop_code_null is thrown when no user owns that invite code — registration is blocked rather than silently dropping the referral.","triggerScenarios":"POST phone-code login with an inviteCode that doesn't match any user's popularize code.","commonSituations":"User hand-typed an invite code with a typo; copied invite link truncated; inviter account deleted after sharing the code; sharing codes across environments with different user bases.","solutions":["Correct the invite code against the inviter's actual code","Retry registration without the inviteCode (it is optional)","Regenerate/share a fresh invite link from the inviter's account"],"exampleFix":"// before\nawait loginApi.loginByPhoneCode(phone, code, inviteCodeTyped); // typo\n// after\ntry {\n  await loginApi.loginByPhoneCode(phone, code, inviteCodeTyped);\n} catch (e) {\n  await loginApi.loginByPhoneCode(phone, code, undefined); // register w/o invite\n}","handlingStrategy":"validation","validationCode":"if (inviteCode) {\n  const inviter = await userService.getUserByPopularizeCode(inviteCode);\n  if (!inviter) inviteCode = undefined; // drop invalid invite before login\n}","typeGuard":"function hasInvite(code?: string): code is string {\n  return typeof code === 'string' && code.trim().length > 0;\n}","tryCatchPattern":"try {\n  await loginApi.loginByPhoneCode(phone, code, inviteCode);\n} catch (e) {\n  if (e.response?.message === 'err_user_pop_code_null') {\n    await loginApi.loginByPhoneCode(phone, code, undefined);\n  }\n}","preventionTips":["Copy invite codes from links instead of typing them","Validate invite code format before submission","Make the invite field optional in the UI with a clear error path"],"tags":["invite-code","registration","validation"],"backgroundTag":"invalid-invite-code","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}