Skip to content

[BUG] Local coding sync session cap counts upserts as new rows #1530

@eshaanag

Description

@eshaanag

Line

src/app/api/local-coding/sync/route.ts:88-91
src/app/api/local-coding/sync/route.ts:111-114
supabase/migrations/20260521000000_add_local_coding_tables.sql:10

Problem

I noticed this while testing the local coding sync path for GSSoC 2026. The sync route counts all rows a user already has, then adds the full incoming newSessions.length before deciding whether the user is over MAX_SESSIONS_PER_USER.

That is not the same as the number of rows that will be inserted. The table has unique(user_id, date), and the route later calls batch_upsert_sessions, so syncing an already-existing date updates the row instead of creating a new one.

Right now, a user with 360 existing local coding days can be blocked from syncing 10 days even if all 10 dates already exist and would only be updates.

Impact

Legitimate re-syncs can fail with Session limit reached near the 365-day cap. That breaks normal retry/backfill behavior for local coding clients, especially if a client sends the last 7/30/90 days every time.

Expected behavior: only truly new dates should count against the 365-session cap.

Current behavior: every valid incoming session is counted as new, even when the RPC would upsert an existing (user_id, date) row.

Reproduction

  1. Have a user with 360 rows in local_coding_sessions.
  2. Send POST /api/local-coding/sync with 10 sessions whose dates already exist for that user.
  3. The route calculates 360 + 10 > 365 and returns 400 Session limit reached.
  4. None of the existing rows are updated, although the database upsert would not increase the row count.

Suggested fix

After validating the incoming sessions, collect their unique dates and query which of those dates already exist for the user. Only add the count of missing dates to existingCount when enforcing MAX_SESSIONS_PER_USER.

A regression test should cover the near-limit case where all incoming dates already exist and should be allowed to sync.

Labels

bug, needs-triage, gssoc26, level:intermediate, type:bug

Metadata

Metadata

Assignees

Labels

gssoc:assignedGSSoC: Issue assigned to a contributor

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions