{"record":{"id":"352692859c18c9d5","repo":"toeverything/AFFiNE","slug":"email-token-not-found-352692","errorCode":"email_token_not_found","errorMessage":"The email token provided is not found.","messagePattern":"The email token provided is not found\\.","errorType":"exception","errorClass":"EmailTokenNotFound","httpStatus":400,"severity":"error","filePath":"packages/backend/server/src/core/auth/resolver.ts","lineNumber":182,"sourceCode":"  ) {\n    return await this.auth.prepareSecurityChallenge(\n      'change_email',\n      user.id,\n      this.url.safeLink(callbackUrl),\n      this.auth.requestSource(context.req)\n    );\n  }\n\n  @Mutation(() => Boolean)\n  async sendVerifyChangeEmail(\n    @CurrentUser() user: CurrentUser,\n    @Args('token') token: string,\n    @Args('email') email: string,\n    @Args('callbackUrl') callbackUrl: string,\n    @Context() context: GraphqlContext\n  ) {\n    if (!token) {\n      throw new EmailTokenNotFound();\n    }\n\n    validators.assertValidEmail(email);\n    return await this.auth.prepareVerifyChangeEmail(\n      user.id,\n      token,\n      email,\n      this.url.safeLink(callbackUrl),\n      this.auth.requestSource(context.req)\n    );\n  }\n\n  @Mutation(() => Boolean)\n  async sendVerifyEmail(\n    @CurrentUser() user: CurrentUser,\n    @Args('callbackUrl') callbackUrl: string,\n    @Context() context: GraphqlContext\n  ) {","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/2af30773aecd567f09b346e7b72fc69143144057/packages/backend/server/src/core/auth/resolver.ts#L164-L200","documentation":"Thrown by sendVerifyChangeEmail when the token argument is falsy. This is a client-precondition failure, distinct from invalid_email_token (185): the mutation was invoked without any token at all, usually because the emailed link did not carry one.","triggerScenarios":"Calling sendVerifyChangeEmail with token: '' or undefined — typically the frontend parsed a URL query param named differently than the link template, or the callbackUrl template omitted the token placeholder so the emailed URL has no token.","commonSituations":"callbackUrl configured without the token substitution placeholder; router reads params.token but the link uses ?t=; a redirect/SSO wrapper strips query strings; user hand-edited the URL.","solutions":["Make sure the callbackUrl passed to sendChangeEmail contains the token placeholder so safeLink injects it","Check the query param name the page reads matches what the link emits","Guard client-side: refuse to call the mutation when the token param is missing and show a 'bad link' page"],"exampleFix":"// before\nawait client.request(sendVerifyChangeEmailMutation, { token: params.get('token') ?? '', email, callbackUrl });\n\n// after\nconst token = params.get('token');\nif (!token) throw new Error('Link is missing its token — check the callbackUrl template');\nawait client.request(sendVerifyChangeEmailMutation, { token, email, callbackUrl });","handlingStrategy":"validation","validationCode":"const token = new URLSearchParams(location.search).get('token');\nif (!token) {\n  renderBadLinkPage('This link is missing its token. Request a new email.');\n} else {\n  await client.request(sendVerifyChangeEmailMutation, { token, email, callbackUrl });\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Include the token placeholder in every callbackUrl template","Use the same query param name in link template and page parser","Never substitute a default empty string for a missing token argument"],"tags":["auth","email","input-validation","graphql"],"backgroundTag":"missing-token-param","analyzedSha":"2af30773aecd567f09b346e7b72fc69143144057","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}