Repository navigation
Description
π§ Project Area
Backend / API
π Issue Summary and Problem Description
Issue summary:
CertiVault has two parallel error hierarchies: ApiError (used across the app) and AppError with rich subclasses (exported but never used). The centralized error handler only checks instanceof ApiError, so any code that imports and throws AppError subclasses (e.g., BadRequestError, NotFoundError) would silently return HTTP 500 instead of the correct status code.
Problem description:
backend/src/common/errors/AppError.tsdefinesBadRequestError(400),UnauthorizedError(401),ForbiddenError(403),NotFoundError(404),ConflictError(409) β a complete, rich hierarchy.backend/src/common/index.ts:9re-exports all of these viaexport * from "./errors/AppError.js", making them part of the public API.backend/src/middleware/errorHandler.ts:25only checkserror instanceof ApiError.- Since
AppErrorsubclasses do NOT extendApiError(they are separate hierarchies), throwing anyAppErrorsubclass would be caught by the genericelsebranch and return HTTP 500 withINTERNAL_SERVER_ERROR.
Why this is important:
This is a ticking time bomb. Any new contributor who sees AppError in the exports and uses it (the natural choice given its descriptive class names) would introduce a silent bug where 400/401/403/404 errors are incorrectly reported as 500s. The error has a 50-100% chance of being deployed without detection because integration tests rarely cover every error path.
Who is affected:
All contributors and API consumers. API clients would receive misleading error codes.
π Current and Expected Behaviour
Current behaviour:
// This compiles fine and is the natural import to use:
import { BadRequestError } from "../common/errors/AppError.js";
throw new BadRequestError("Invalid input");
// Result: HTTP 500 INTERNAL_SERVER_ERROR (wrong!)Expected behaviour:
throw new BadRequestError("Invalid input");
// Should return: HTTP 400 BAD_REQUESTπ§© Reproduction and Evidence
Step 1: Add `throw new BadRequestError("test")` to any controller
Step 2: Call the endpoint
Step 3: Observe HTTP 500 instead of 400Evidence:
backend/src/common/errors/AppError.tsβ definesBadRequestError(400),UnauthorizedError(401),ForbiddenError(403),NotFoundError(404),ConflictError(409)backend/src/common/index.ts:9βexport * from "./errors/AppError.js"backend/src/middleware/errorHandler.ts:25β only checkserror instanceof ApiErrorbackend/src/middleware/errorHandler.ts:29-38β the else branch catches everything else asINTERNAL_SERVER_ERROR
π― Affected Scope
Affected files:
backend/src/common/errors/AppError.ts(the unused hierarchy)backend/src/middleware/errorHandler.ts(only handlesApiError)backend/src/common/index.ts(re-exports the broken hierarchy)
Affected APIs:
Any API endpoint where an AppError subclass is thrown instead of ApiError.
Affected components:
Error handling middleware, all modules that might use AppError.
Database changes required? No
π₯ Environment
Operating system: N/A (code design issue)
Node.js version: v22.x
Package manager: npm 10.x
Deployment environment: All
π‘ Solution, Alternatives, and Estimate
Priority: P1 High
Proposed solution:
Choose one hierarchy and use it consistently. Recommended approach:
- Make
AppErrorextendApiError(or vice versa) so theinstanceofcheck catches both - Update
errorHandler.tsto check for both hierarchies - Remove the unused hierarchy and update all imports to use the surviving one
Alternative solutions:
- Add
error instanceof AppErrorcheck inerrorHandler.tsalongside theApiErrorcheck - Merge both into a single hierarchy under
common/errors/
Difficulty: Intermediate
Estimated time: 3-5 hours
Dependencies or blockers: None
β Acceptance Criteria and Additional Notes
- Throwing
BadRequestErrorreturns HTTP 400 - Throwing
UnauthorizedErrorreturns HTTP 401 - Throwing
NotFoundErrorreturns HTTP 404 - Throwing
ApiErrorstill returns the correct status code - All existing integration tests pass
- One hierarchy is removed or deprecated with a clear migration path
Additional notes:
The AppError hierarchy is actually better designed (inheritance tree, named subclasses) β it would be ideal to promote AppError and deprecate ApiError. But whichever direction is chosen, consistency is the goal.
π€ Contributor Checklist
- I have searched existing issues and pull requests for duplicates.
- I can reproduce the issue, or I have clearly explained why reproduction is not applicable.
- I will follow the contribution guidelines and target
ecsoc-2026. - I agree to follow the Code of Conduct.
- I have removed secrets, private documents, and personal data.
Activity
Atharv094 commentedon Aug 3, 2026
Hi maintainers! Iβd love to take this on. Since
errorHandler.tsonly checksinstanceof ApiError,AppErrorsubclasses likeBadRequestErrorincorrectly throw HTTP 500. I can unify the hierarchies so all errors return correct status codes. Please assign this to me.Is this issue under the ECSoC program? If so, could you please add the "EcSoc26" label?
Dhruvi2006-source commentedon Aug 30, 2026
/claim