Nobody has started this yet — be first.
Business impact
A user tagging a note with a maximally-long tag (right at the documented 50-character limit) gets a 422 validation error for no visible reason -- the tag "looks fine," is under the length shown anywhere in the docs, and yet the API refuses it. It's a small paper cut, but it's the kind of inconsistency that erodes trust in /docs as an accurate contract (the README's whole pitch is that the schema is trustworthy). Low priority since it only bites at one exact length, but it's a one-line fix and worth clearing out.
Problem
TAG_MAX_LENGTH = 50 is documented (by name and by every other bound in this file, e.g. MAX_TAGS) as the maximum number of characters a tag is allowed to have -- i.e. 50 should be a valid length, not the first invalid one. But the validator rejects a tag of exactly 50 characters, while accepting one of 49.
Current behavior
POST /notes with a tag of exactly 50 characters returns 422 Unprocessable Entity ("tag '...' exceeds 50 characters"), even though the tag is exactly at the documented limit, not over it.
Expected behavior
A tag of exactly TAG_MAX_LENGTH (50) characters is accepted. Only tags longer than 50 characters should be rejected.
Steps to reproduce
cd fastapi/notes_api
source .venv/bin/activate
uvicorn app.main:app --reload &
curl -s -X POST http://127.0.0.1:8000/notes
-H "Content-Type: application/json"
-d "{"title":"t","content":"c","tags":["$(python3 -c 'print("a"*50)')"]}"
Why this matters
This is a classic inclusive-vs-exclusive boundary bug. The check compares len(cleaned) against TAG_MAX_LENGTH with the wrong operator, so the boundary value itself falls on the wrong side of the comparison.
Suggested approach
Look at _normalize_tags in app/schemas.py. Compare the current comparison operator against what "at most TAG_MAX_LENGTH characters" actually means for a length check, and against how MAX_TAGS is checked a few lines below for the pattern this file already uses elsewhere.
Acceptance criteria
Verification
.venv/bin/pytest practicetickets/test_ticket01_tag_length_boundary.py -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/tag-length-boundaryFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/tag-length-boundarySubmit 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 in./data/notes.dbOr run it via Docker instead:
cd fastapi/notes_api
docker compose up --build # API on http://127.0.0.1:8000, /docs included
SQLite data is written inside the container to /app/data/notes.db, backed by the notes-data named volume declared in docker-compose.yml -- it survives docker compose restart and re-running docker compose up after down (without -v).
Work the tickets in practicetickets/ (ticket01 through ticket07); each names one pytest file in the same directory, separate from the project's own tests/ suite:
.venv/bin/pytest practicetickets/test_ticket01_tag_length_boundary.py -v # a single ticket
./practicetickets/run_tickets.sh # all 7, pass/fail summary
./practicetickets/run_tickets.sh -v # summary + full output
Note: ticket 02's bug also breaks two pre-existing tests in tests/test_notes.py (test_search_by_q_matches_title_and_content_case_insensitively and test_filter_by_tag_and_q_are_combinable) -- that's expected, and fixing ticket 02 should bring tests/ back to fully green. Run the main suite with .venv/bin/pytest tests/ -v.
Level 1
Fix a bug
Read existing behaviour, correct it.