{"record":{"id":"bdc505e85ee8ba85","repo":"calcom/cal.diy","slug":"invalid-verification-code","errorCode":null,"errorMessage":"Invalid verification code","messagePattern":"Invalid verification code","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apps/api/v2/src/modules/atoms/services/verification-atom.service.ts","lineNumber":34,"sourceCode":"\n@Injectable()\nexport class VerificationAtomsService {\n  constructor(\n    private readonly atomsSecondaryEmailsRepository: AtomsSecondaryEmailsRepository,\n    private readonly usersRepository: UsersRepository\n  ) {}\n\n  async checkEmailVerificationRequired(input: CheckEmailVerificationRequiredParams) {\n    return await checkEmailVerificationRequired(input);\n  }\n\n  async verifyEmailCodeUnAuthenticated(input: VerifyEmailCodeInput) {\n    try {\n      return await verifyCodeUnAuthenticated(input.email, input.code);\n    } catch (error) {\n      if (error instanceof Error) {\n        if (error.message === \"invalid_code\") {\n          throw new BadRequestException(\"Invalid verification code\");\n        }\n        if (error.message === \"BAD_REQUEST\") {\n          throw new BadRequestException(\"Email and code are required\");\n        }\n      }\n      throw new BadRequestException(\"Verification failed\");\n    }\n  }\n\n  async verifyEmailCodeAuthenticated(user: UserWithProfile, input: VerifyEmailCodeInput) {\n    try {\n      return await verifyCodeAuthenticated({\n        user,\n        email: input.email,\n        code: input.code,\n      });\n    } catch (error) {\n      if (error instanceof Error) {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/atoms/services/verification-atom.service.ts#L16-L52","documentation":"Thrown by VerificationAtomService.verifyEmailCodeUnAuthenticated when the underlying verifyCodeUnAuthenticated rejects with an Error whose message equals 'invalid_code'. It is meant to map an upstream 'wrong/expired TOTP code' failure into a 400 Bad Request with a user-friendly message. The TOTP code is derived from md5(email + CALENDSO_ENCRYPTION_KEY) with a 900s step, so any code older than ~15 min or computed with a different key will fail. IMPORTANT: under the current source this branch is effectively DEAD — verifyCodeUnAuthenticated throws new Error('Invalid verification code') (not 'invalid_code'), so the message match never succeeds and the catch falls through to the generic 'Verification failed' (error 22).","triggerScenarios":"POST to the atoms verify-email-code-unauthenticated endpoint with an email/code pair where the upstream library threw an Error literally equal to 'invalid_code'. Because the upstream never emits that exact string today, this only triggers if the upstream contract is changed to throw 'invalid_code', or if a rate-limit/other error happens to be renamed.","commonSituations":"Developer enters a wrong 6-digit verification code; developer enters an expired code (older than the 900s TOTP step); CALENDSO_ENCRYPTION_KEY differs between code-generation and verification environments; upstream library version change that alters thrown error message strings.","solutions":["If you are a platform maintainer: align the catch predicate with the real upstream message — compare against 'Invalid verification code' (or better, throw a typed ErrorWithCode from verifyCodeUnAuthenticated and check with instanceof) so this branch actually fires.","As an API caller: request a fresh verification code and retry within the 15-minute TOTP window.","Verify CALENDSO_ENCRYPTION_KEY is identical on the service that issued the code and the service verifying it.","Inspect the actual upstream error message in a debugger to confirm the mismatch before patching the predicate."],"exampleFix":"// before\nif (error.message === \"invalid_code\") {\n  throw new BadRequestException(\"Invalid verification code\");\n}\n\n// after — match the real upstream message (or use a typed error)\nif (error.message === \"Invalid verification code\" || error.message === \"invalid_code\") {\n  throw new BadRequestException(\"Invalid verification code\");\n}","handlingStrategy":"try-catch","validationCode":"// Validate before calling verifyEmailCodeUnAuthenticated\nconst emailOk = typeof input.email === 'string' && input.email.includes('@') && input.email.length > 3;\nconst codeOk = typeof input.code === 'string' && /^\\d{6}$/.test(input.code);\nif (!emailOk || !codeOk) throw new BadRequestException('Email and code are required');","typeGuard":"function isVerifyEmailCodeInput(v: unknown): v is { email: string; code: string } {\n  return typeof v === 'object' && v !== null &&\n    typeof (v as any).email === 'string' &&\n    typeof (v as any).code === 'string';\n}","tryCatchPattern":"try {\n  await service.verifyEmailCodeUnAuthenticated(input);\n} catch (e) {\n  // NOTE: today this is the generic 'Verification failed' (error 22), not this message.\n  if (e instanceof BadRequestException && e.message === 'Invalid verification code') {\n    // prompt user to re-enter code\n  }\n  throw e;\n}","preventionTips":["Request a fresh code and submit within the 15-minute TOTP window.","Keep CALENDSO_ENCRYPTION_KEY identical between code issuer and verifier.","Validate the 6-digit shape before hitting the endpoint to avoid wasted attempts and rate-limit tripping."],"tags":["verification","totp","dead-branch","error-message-mismatch","atoms-api"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}