Nobody has started this yet — be first.
Business impact
DELETE /bookmarks/{id} on a bookmark that actually exists reports 404 Not Found -- even though the row genuinely gets deleted from the database in the same call. A client sees a failure, may retry or show an error to the user ("couldn't delete that"), while the delete silently succeeded. This is worse than a bug that does nothing: it actively misinforms the caller about what happened.
Problem
After the DELETE SQL executes, Store.Delete checks res.RowsAffected() to decide whether a row was actually removed (0 rows = nothing matched = not found). That check has been changed to a comparison that's true for every possible value RowsAffected can return, so it reports "not found" unconditionally -- even immediately after successfully deleting a row that definitely existed.
Current behavior
DELETE /bookmarks/{id} on an id that exists returns 404, but a follow-up GET on the same id confirms the row is actually gone.
Expected behavior
Store.Delete returns ErrNotFound only when zero rows were actually affected; a successful delete of an existing row returns nil (and the HTTP layer responds 204).
Steps to reproduce
ID=$(curl -s -X POST http://localhost:8081/bookmarks -H 'Content-Type: application/json'
-d '{"url":"https://example.com","title":"Test"}' | jq -r .id)
curl -i -X DELETE http://localhost:8081/bookmarks/$ID
Why this matters
RowsAffected() can never be negative, so a comparison that's meant to distinguish "zero rows changed" from "one row changed" needs to actually test for zero -- a boundary-comparison mistake here doesn't fail loudly (no panic, no type error), it just always takes one branch, which is exactly the kind of defect that slips through casual manual testing (an occasional "huh, that's weird" 404 someone shrugs off).
Suggested approach
Look at the comparison against n (the value RowsAffected() returned) right after the DELETE executes, and work out which values of n should mean "nothing was deleted."
Acceptance criteria
Verification
go test ./practicetickets/... -run TestTicket06 -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
$git checkout -b fix/delete-reports-404-on-successFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/delete-reports-404-on-successSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inmigrations/0001_init.sqlcurl http://localhost:8081/healthz
# {"status":"ok"}
To run without Docker, point the DB_* env vars from .env.example at a reachable Postgres and run go run ./cmd/server -- it applies the same migrations on startup.
The project's own test suite (go test ./...) is an integration suite against a real Postgres; it looks for one via BM_TEST_DB_HOST/BM_TEST_DB_PORT/BM_TEST_DB_USER/BM_TEST_DB_PASSWORD/BM_TEST_DB_NAME (defaults point at localhost:15433, database bookmarks_test) and skips cleanly rather than failing if that database is unreachable:
docker run -d --name bm_test_pg -e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=bookmarks_test -p 15433:5432 postgres:16-alpine
Work the tickets in PRACTICE_TICKETS.md (TICKET-01 through TICKET-10, all in one file, ordered easy -> hard); each names one Go test under practicetickets/:
go test ./practicetickets/... -run TestTicket01 -v # a single ticket
./practice_tickets_run.sh # all 10, clean pass/fail summary table
Level 1
Fix a bug
Read existing behaviour, correct it.