Nobody has started this yet — be first.
Business impact
An owner trying to create a form with a field name that happens to be exactly 100 characters long gets a confusing rejection -- "'name' exceeds 100 characters" -- even though the name does not exceed 100 characters, it equals it. This is a paper-cut for a human typing a long field name by hand, but it is a sharper edge for anyone integrating programmatically: a script that trims field names to the documented 100-character limit before submitting will get inconsistent 422s depending on whether the trimmed name happens to land at exactly 100 characters, with no obvious explanation in the error message for why an apparently within-limit name was rejected. Low severity, but exactly the kind of thing that generates a confused support ticket ("your docs say 100, I sent 100, it failed") that costs real time to triage.
Problem
validate_field_definitions() is supposed to reject field names longer than MAX_FIELD_NAME_LEN (100 characters). Right now it also rejects names exactly at that length.
Current behavior
Creating a form with a field name of exactly 100 characters returns 422 ("'name' exceeds 100 characters") instead of 201, even though the name does not exceed the documented limit.
Expected behavior
A field name of exactly 100 characters is accepted. A field name of 101+ characters is still rejected (this side already works and must keep working).
Steps to reproduce
cd flask/feedback_service export FLASK_ENV=testing .venv/bin/python -c " from app import create_app from app.extensions import db
app = create_app('testing') with app.app_context(): db.create_all() client = app.test_client()
reg = client.post('/api/auth/register', json={'email': 'a@example.com', 'password': 'supersecret123'}) token = reg.get_json()['access_token'] headers = {'Authorization': f'Bearer {token}'}
name_100 = 'x' * 100 resp = client.post('/api/forms', json={'title': 't', 'fields': [{'name': name_100, 'type': 'text'}]}, headers=headers) print(resp.status_code, resp.get_json()) "
Why this matters
MAX_FIELD_NAME_LEN = 100 is documented (by the error message itself, and by convention) as the maximum allowed length, not the first disallowed length. A value of exactly the limit satisfying "exceeds the limit" is a classic boundary/off-by-one mistake, and it is worth practicing spotting these because they are extremely common in real input-validation code (pagination limits, string-length checks, rate windows, buffer sizes -- the same shape of bug shows up everywhere).
Suggested approach
Look at the single comparison in validate_field_definitions that decides whether a field name is too long. Compare it, character by character, against what the error message it produces actually claims ("exceeds N characters"). Python's comparison operators are exact tools here -- make sure the one used matches the English in the error string.
Acceptance criteria
Verification
cd flask/feedback_service && FLASK_ENV=testing .venv/bin/python -m pytest ticket_tests/test_ticket_01_field_name_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/field-name-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/field-name-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 inweb and worker share the same image and only differ in their command: -- web runs flask db upgrade && flask run, worker runs celery -A celery_worker.celery worker. For a prod-style stack (built image, gunicorn, no bind mount) use docker compose -f docker-compose.prod.yml up --build instead; it refuses to start without SECRET_KEY/JWT_SECRET_KEY actually set in the environment.
cd flask/feedback_service
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # defaults are fine for local dev as-is
export FLASK_APP=wsgi.py FLASK_ENV=development
flask db upgrade # applies migrations to a fresh SQLite DB under instance/
# terminal 1
flask run --port 5000
# terminal 2 (needs a local redis-server running — broker for both Celery and the rate limiter)
celery -A celery_worker.celery worker --loglevel=info
Each ticket in ticket_tests/tickets/0N_*.md names one dedicated test file under ticket_tests/:
cd flask/feedback_service
export FLASK_ENV=testing
.venv/bin/python -m pytest ticket_tests/test_ticket_0N_*.py -v # a single ticket
./ticket_tests/run_tickets.sh # all 7, PASS/FAIL scoreboard
TestingConfig runs Celery tasks eagerly (CELERY_TASK_ALWAYS_EAGER=True, no broker needed) and uses a real, per-test-flushed Redis DB for the rate limiter when Redis is reachable, falling back to Flask-Limiter's in-memory backend otherwise -- either way the real Flask-Limiter code path runs, nothing about rate limiting is mocked. Note ticket_tests/ is not collected by a plain pytest -q from the project root (pytest.ini pins testpaths = tests), so the project's own suite and this practice suite stay independent and must be run explicitly.
Level 1
Fix a bug
Read existing behaviour, correct it.