Skip to content

[Bug] DSA sheet progress never persists — saveProgress rejects the object completedTopics shape with 400 #1727

Description

@vedant7007

Description

DSA-sheet progress never persists to the backend: saveProgress rejects the correct completedTopics object/map shape with a 400, because a hand-rolled check requires an array — contradicting the Zod validator, the Mongoose schema, the import util, and the frontend.

backend/controllers/userSheetProgressController.js (~L63-68):

if (completedTopics !== undefined && !Array.isArray(completedTopics)) {
  return res.status(400).json({ success:false, error:"Invalid completedTopics field, must be an array" });
}

The frontend POSTs an object, e.g. { sheetId, followed:true, completedTopics:{ "0-0-0":true }, percentage:12 } (frontend/src/components/SheetDetailsPage.jsx:198, ProgressTrackerDashboard.jsx:153). The Zod validator permits it (completedTopics: z.record(z.string(), z.boolean())), and the schema is completedTopics: { type: Object }, resetProgress sets {}, and the import util returns an object. Only this controller check disagrees, and !Array.isArray({...}) is trueevery save returns 400. The frontend .catch swallows it, so progress lives only in localStorage and is silently lost across devices / on cache clear.

(Distinct from the existing race-condition retry issue — this is the payload shape being rejected outright.)

Fix

Accept a plain object:

if (completedTopics !== undefined &&
    (typeof completedTopics !== "object" || completedTopics === null || Array.isArray(completedTopics))) {
  return res.status(400).json({ success:false, error:"Invalid completedTopics field, must be an object" });
}

(or delete the redundant manual checks and rely on the wired validateSaveProgress).

Happy to fix if assigned.

Contributing as part of Elite Coders Summer of Code (ECSoC 2026).

Metadata

Metadata

Assignees

Labels

claimedThis issue has been claimed by a contributor

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions