yikart/AiToEarn · error · Error

Google login failed: ${error.message}

Error message

Google login failed: ${error.message}

What it means

googleLogin wraps its entire body in try/catch; on any failure (token verification, user lookup, account linking, token issuance) it logs and rethrows as Error(`Google login failed: ${error.message}`). The original cause is preserved only in the message string, so the underlying error (e.g. 'Invalid Google token', DB failure, network error) is flattened.

Source

Thrown at project/aitoearn-electron/server/src/modules/plat/google/google.service.ts:511

      // const expires = 30 * 24 * 60 * 60
      // console.log("accessTokenInfo:---", accessTokenInfo);
      // console.log("expires:---", accessTokenInfo.expires_in);
      // this.redisService.setKey(
      //   `google:accessToken:${userId}`,
      //   accessTokenInfo,
      //   accessTokenInfo.expires_in
      // );
      const loginResult = {
        token: null,
        type: "login",
        userInfo: TokenInfo
      }
      loginResult.token = systemToken
      return loginResult;
    } catch (error) {
      console.error('Google login error:', error);
      throw new Error(`Google login failed: ${error.message}`);
    }
  }

  async setUserAccessToken_V2(data: {
    code: string;
    state: string;
  }) {

    const { code, state } = data;
    console.log("================ code state=======================")
    console.log(code, state);
    console.log("=============================================")

    try {
      const params = new URLSearchParams({
        code: code,
        redirect_uri: `${this.webRenderBaseUrl}/api/plat/google/auth/accessToken`,
        client_id: this.webClientId,

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Read the inner error.message in the thrown string to identify the root cause (it is appended)
  2. Log the full error stack, not just message, before rethrowing
  3. Preserve the original error via { cause: error } so instanceof checks and stacks survive
  4. Handle known causes specifically (invalid token -> 401, DB conflict -> 409) instead of one generic message
  5. In the client, surface the inner message to guide the user (e.g. re-authenticate)

Example fix

// before
} catch (error) {
  console.error('Google login error:', error);
  throw new Error(`Google login failed: ${error.message}`);
}
// after
} catch (error) {
  console.error('Google login error:', error);
  throw new Error(`Google login failed: ${error.message}`, { cause: error });
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  return await googleService.googleLogin(idToken, clientId);
} catch (err) {
  const cause = err?.cause?.message || err.message;
  logger.error('Google login failed', cause);
  if (cause.includes('Invalid Google token')) return res.status(401).end();
  return res.status(502).json({ error: 'Google login unavailable' });
}

Prevention

When it happens

Trigger: Any exception thrown inside googleLogin — including verifyIdToken failures (expired/invalid token, audience mismatch), database errors when creating/linking the Google account, or downstream token generation — is rethrown with this message.

Common situations: Expired or tampered ID token; token issued for a different clientId; MongoDB/DB unique constraint when linking an already-linked Google account; network failure calling Google tokeninfo; bugs in subsequent token minting.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/6845baecacbf26d5. Report an issue: GitHub.