Skip to content

fix: add try-catch around JSON.parse(userData) in auth services#88

Open
lawrence3699 wants to merge 1 commit intoAkkalDhami:mainfrom
lawrence3699:fix/json-parse-error-handling-auth-service
Open

fix: add try-catch around JSON.parse(userData) in auth services#88
lawrence3699 wants to merge 1 commit intoAkkalDhami:mainfrom
lawrence3699:fix/json-parse-error-handling-auth-service

Conversation

@lawrence3699
Copy link
Copy Markdown

@lawrence3699 lawrence3699 commented Apr 2, 2026

Summary

JSON.parse(userData) in the auth service verifyEmail flow can throw SyntaxError if Redis stores corrupted/invalid JSON. While the null check validates userData exists, it doesn't validate JSON format.

Added try-catch with ApiError.badRequest across all 6 affected template variants (hybrid-auth and stateless-auth for MongoDB, PostgreSQL, MySQL).

Test plan

  • Valid OTP verification flow still works
  • Corrupted Redis data returns 400 instead of crashing

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced error handling in authentication services across multiple templates. When user data cannot be processed, the system now returns a clear, user-friendly error message instead of exposing technical errors, improving the reliability of authentication operations.

Copilot AI review requested due to automatic review settings April 2, 2026 05:12
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 2, 2026

@lawrence3699 is attempting to deploy a commit to the akkaldhami's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

JSON parsing error handling was enhanced across multiple authentication service templates. The AuthService.verifyUser method now wraps JSON.parse(userData) calls in try/catch blocks, throwing a standardized ApiError.badRequest("Invalid user data format") on parsing failure instead of propagating raw errors.

Changes

Cohort / File(s) Summary
Hybrid Auth MongoDB/Mongoose
packages/templates/node/express/blueprint/hybrid-auth/mongodb/mongoose/feature/src/modules/auth/auth.service.ts, packages/templates/node/express/blueprint/hybrid-auth/mongodb/mongoose/mvc/src/services/auth.service.ts
Wrapped JSON.parse(userData) in try/catch block; throws ApiError.badRequest("Invalid user data format") on parse failure; destructures parsed result into name, email, role, password.
Hybrid Auth PostgreSQL/Drizzle
packages/templates/node/express/blueprint/hybrid-auth/postgresql/drizzle/feature/src/modules/auth/auth.service.ts, packages/templates/node/express/blueprint/hybrid-auth/postgresql/drizzle/mvc/src/services/auth.service.ts
Introduced parsedData variable with guarded JSON parsing in try/catch; throws standardized error on parse failure; destructures from parsedData instead of direct parse result.
Stateless Auth MySQL/Drizzle
packages/templates/node/express/blueprint/stateless-auth/mysql/drizzle/feature/src/modules/auth/auth.service.ts, packages/templates/node/express/blueprint/stateless-auth/mysql/drizzle/mvc/src/services/auth.service.ts
Implemented try/catch wrapper for JSON.parse(userData); throws ApiError.badRequest("Invalid user data format") on failure; destructures parsed data into named variables.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A parse that once would crash and burn,
Now catches errors, learns to turn
Raw JSON data, safe and sound—
With try and catch, no bugs are found! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding try-catch error handling around JSON.parse(userData) in auth services across the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@packages/templates/node/express/blueprint/hybrid-auth/postgresql/drizzle/feature/src/modules/auth/auth.service.ts`:
- Around line 127-133: The code parses userData into parsedData but then
destructures without validating shape, so values like null or arrays will cause
runtime errors or bad inserts; in auth.service.ts add a type guard after
JSON.parse that checks parsedData is a non-null plain object (typeof parsedData
=== "object" && parsedData !== null && !Array.isArray(parsedData)), then verify
required fields (name, email, password, optional role) exist and have expected
primitive types (e.g., strings) and otherwise throw ApiError.badRequest("Invalid
user data format"); only after these checks perform the destructuring and
proceed to the DB insert (the block that currently destructures name, email:
userEmail, role, password and inserts on the following lines).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 325653c4-492e-447d-ae95-7756d8dbc8cd

📥 Commits

Reviewing files that changed from the base of the PR and between ed5a1d4 and 7dede5f.

📒 Files selected for processing (6)
  • packages/templates/node/express/blueprint/hybrid-auth/mongodb/mongoose/feature/src/modules/auth/auth.service.ts
  • packages/templates/node/express/blueprint/hybrid-auth/mongodb/mongoose/mvc/src/services/auth.service.ts
  • packages/templates/node/express/blueprint/hybrid-auth/postgresql/drizzle/feature/src/modules/auth/auth.service.ts
  • packages/templates/node/express/blueprint/hybrid-auth/postgresql/drizzle/mvc/src/services/auth.service.ts
  • packages/templates/node/express/blueprint/stateless-auth/mysql/drizzle/feature/src/modules/auth/auth.service.ts
  • packages/templates/node/express/blueprint/stateless-auth/mysql/drizzle/mvc/src/services/auth.service.ts

Comment on lines +127 to +133
let parsedData;
try {
parsedData = JSON.parse(userData);
} catch {
throw ApiError.badRequest("Invalid user data format");
}
const { name, email: userEmail, role, password } = parsedData;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "auth.service.ts" | grep -E "auth/auth.service.ts"

Repository: AkkalDhami/servercn

Length of output: 753


🏁 Script executed:

cat -n "packages/templates/node/express/blueprint/hybrid-auth/postgresql/drizzle/feature/src/modules/auth/auth.service.ts" | sed -n '115,145p'

Repository: AkkalDhami/servercn

Length of output: 1128


Validate parsed JSON shape before destructuring.

JSON.parse failure is handled, but line 133 still assumes an object payload. Valid JSON like null bypasses the catch and throws a TypeError during destructuring. This can result in unhandled errors and potentially invalid data being inserted into the database on line 140-144.

Add a type guard to ensure parsedData is an object before destructuring:

Proposed fix
-    let parsedData;
+    let parsedData: unknown;
     try {
       parsedData = JSON.parse(userData);
     } catch {
       throw ApiError.badRequest("Invalid user data format");
     }
-    const { name, email: userEmail, role, password } = parsedData;
+    if (!parsedData || typeof parsedData !== "object") {
+      throw ApiError.badRequest("Invalid user data format");
+    }
+
+    const {
+      name,
+      email: userEmail,
+      role,
+      password
+    } = parsedData as Partial<{
+      name: string;
+      email: string;
+      role: string;
+      password: string;
+    }>;
+
+    if (
+      typeof name !== "string" ||
+      typeof userEmail !== "string" ||
+      typeof password !== "string"
+    ) {
+      throw ApiError.badRequest("Invalid user data format");
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/templates/node/express/blueprint/hybrid-auth/postgresql/drizzle/feature/src/modules/auth/auth.service.ts`
around lines 127 - 133, The code parses userData into parsedData but then
destructures without validating shape, so values like null or arrays will cause
runtime errors or bad inserts; in auth.service.ts add a type guard after
JSON.parse that checks parsedData is a non-null plain object (typeof parsedData
=== "object" && parsedData !== null && !Array.isArray(parsedData)), then verify
required fields (name, email, password, optional role) exist and have expected
primitive types (e.g., strings) and otherwise throw ApiError.badRequest("Invalid
user data format"); only after these checks perform the destructuring and
proceed to the DB insert (the block that currently destructures name, email:
userEmail, role, password and inserts on the following lines).

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds defensive handling around parsing cached signup payloads from Redis during OTP/email verification in the Node/Express auth templates, preventing invalid/corrupted JSON from propagating as an unhandled exception.

Changes:

  • Wraps JSON.parse(userData) in try/catch during the OTP verification flow.
  • Converts JSON parse failures into ApiError.badRequest("Invalid user data format") across the affected template variants.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/templates/node/express/blueprint/stateless-auth/mysql/drizzle/mvc/src/services/auth.service.ts Adds try/catch around parsing Redis-stored signup payload in verifyUser.
packages/templates/node/express/blueprint/stateless-auth/mysql/drizzle/feature/src/modules/auth/auth.service.ts Same parse-guard in feature-module variant.
packages/templates/node/express/blueprint/hybrid-auth/postgresql/drizzle/mvc/src/services/auth.service.ts Same parse-guard in hybrid Postgres MVC variant.
packages/templates/node/express/blueprint/hybrid-auth/postgresql/drizzle/feature/src/modules/auth/auth.service.ts Same parse-guard in hybrid Postgres feature variant.
packages/templates/node/express/blueprint/hybrid-auth/mongodb/mongoose/mvc/src/services/auth.service.ts Same parse-guard in hybrid Mongo MVC variant.
packages/templates/node/express/blueprint/hybrid-auth/mongodb/mongoose/feature/src/modules/auth/auth.service.ts Same parse-guard in hybrid Mongo feature variant.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +93 to +98
let parsedData;
try {
parsedData = JSON.parse(userData);
} catch {
throw ApiError.badRequest("Invalid user data format");
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If JSON.parse(userData) fails here, OTP has already been consumed by OtpService.verifyOtp, but the Redis user:${email}:${hashCode} key is left behind until TTL. Consider best-effort deleting that key in the catch before throwing so corrupted/sensitive cached signup data doesn’t linger and the user can restart the flow cleanly.

Copilot uses AI. Check for mistakes.
Comment on lines +96 to +101
let parsedData;
try {
parsedData = JSON.parse(userData);
} catch {
throw ApiError.badRequest("Invalid user data format");
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If JSON.parse(userData) fails here, OTP has already been consumed by OtpService.verifyOtp, but the Redis user:${email}:${hashCode} key is left behind until TTL. Consider best-effort deleting that key in the catch before throwing so corrupted/sensitive cached signup data doesn’t linger and the user can restart the flow cleanly.

Copilot uses AI. Check for mistakes.
let parsedData;
try {
parsedData = JSON.parse(userData);
} catch {
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On JSON.parse failure, OTP has already been consumed, but the pending-signup keys remain (user:${email}:${hashCode} and user:pending:${email}) until TTL. That can leave a user stuck in “signup already in progress” with no usable OTP; consider best-effort deleting both keys in this catch before throwing.

Suggested change
} catch {
} catch (error) {
await Promise.allSettled([
redisClient.del(`user:${email}:${hashCode}`),
redisClient.del(`user:pending:${email}`)
]);

Copilot uses AI. Check for mistakes.
Comment on lines +127 to +132
let parsedData;
try {
parsedData = JSON.parse(userData);
} catch {
throw ApiError.badRequest("Invalid user data format");
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On JSON.parse failure, OTP has already been consumed, but the pending-signup keys remain (user:${email}:${hashCode} and user:pending:${email}) until TTL. That can leave a user stuck in “signup already in progress” with no usable OTP; consider best-effort deleting both keys in this catch before throwing.

Copilot uses AI. Check for mistakes.
let parsedData;
try {
parsedData = JSON.parse(userData);
} catch {
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On JSON.parse failure, OTP has already been consumed, but the pending-signup keys remain (user:${email}:${hashCode} and user:pending:${email}) until TTL. That can leave a user stuck in “signup already in progress” with no usable OTP; consider best-effort deleting both keys in this catch before throwing.

Suggested change
} catch {
} catch (parseError) {
// Best-effort cleanup to avoid leaving the user stuck with a pending signup
try {
await redisClient.del(`user:${email}:${hashCode}`);
await redisClient.del(`user:pending:${email}`);
} catch (cleanupError) {
logger.error(
cleanupError,
"Failed to clean up pending signup keys after JSON parse error"
);
}

Copilot uses AI. Check for mistakes.
let parsedData;
try {
parsedData = JSON.parse(userData);
} catch {
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On JSON.parse failure, OTP has already been consumed, but the pending-signup keys remain (user:${email}:${hashCode} and user:pending:${email}) until TTL. That can leave a user stuck in “signup already in progress” with no usable OTP; consider best-effort deleting both keys in this catch before throwing.

Suggested change
} catch {
} catch {
// Best-effort cleanup to avoid leaving the user stuck in "signup already in progress"
await redisClient.del(`user:${email}:${hashCode}`);
await redisClient.del(`user:pending:${email}`);

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants