Spot the bug: Flask notes API

Ten short Flask endpoints, one bug each. Tap the line that breaks, then see the request that exposes it, the fix, and the one rule behind it.

Every card is part of a small notes API. store is an in-memory store with create, get, update and delete. It trusts whatever it is given, so checking the request is the endpoint's job.

Create a note

Should: POST /notes creates a note and answers 201 Created with the note.

Tap the line with the bug.

Read a note by id

Should: GET /notes/<id> returns the note, or 404 if there is none.

The store already holds note 1: “Buy milk”.

Tap the line with the bug.

Reject blank text

Should: POST /notes answers 400 when text is missing, empty or only spaces.

Tap the line with the bug.

Found or not found

Should: GET /notes/<id> returns the note, or 404 if there is none.

The store already holds note 1: “Buy milk”.

Tap the line with the bug.

Not a JSON object

Should: POST /notes answers 400 for any body that isn't a JSON object with text.

Tap the line with the bug.

Delete a note

Should: DELETE /notes/<id> answers 204, or 404 if there is no such note.

Tap the line with the bug.

Edit a note

Should: PATCH /notes/<id> replaces the note's text with the text in the request.

The store already holds note 1: “Buy milk”.

Tap the line with the bug.

Body that isn't JSON

Should: POST /notes answers 400 {"error": "text is required"} for any bad body.

Tap the line with the bug.

Where ids come from

Should: Every new note gets an id no other note has.

4
10

Tap the line with the bug.

Who picks the id

Should: POST /notes stores the text; the server picks the id.

3

Tap the line with the bug.

Done

The 10 rules

  1. Something was created → return 201, not the default 200.
  2. Parts of a URL arrive as strings: use <int:note_id> for numeric ids.
  3. .strip() never returns None: test for blank with not text.strip().
  4. One return per outcome: don't squeeze two responses into one line.
  5. Check the type first: isinstance(data, dict) before in or .get().
  6. Check the id exists (404) before update or delete.
  7. Validate what the client sent, not what you already stored.
  8. Use get_json(silent=True), so bad bodies reach your own 400.
  9. Ids come from a counter that only goes up, never from len().
  10. Copy only the fields you expect; never spread client JSON into a record.

More in Divero School