Known Issues & Limitations
Version 2 · Added qdb/qdg naming inconsistency, unrouted meeting templates, and confirmed root-cause detail for the sectional-data gap; noted FEATURES.md is partly stale
Historical versionRunner Form — Known Issues & Limitations
Open: hard-coded login credentials
Status: Open — dev-only, must fix before production.
Symptoms: Login accepts a single hard-coded username/password checked directly in
views.py, not Django's user system.
Cause: Custom session auth was written for local development speed; @custom_login_required
only checks request.session['is_authenticated'].
Workaround: Acceptable for local/dev use only.
Resolution: Replace with proper Django user accounts or OAuth before any production or
shared deployment.
Open: DB credentials stored in plain text
Status: Open.
Symptoms: MySQL connection details, including the database password, live directly in
config/settings.py in plain text.
Cause: No .env/environment-variable layer was set up.
Workaround: None — treat the repository as sensitive.
Resolution: Move DB credentials to environment variables before production.
Open: single-process cache
Status: Open — functional, but won't scale.
Symptoms: Django's default in-memory cache is per-process; cached form/search/date data is
not shared across multiple IIS/wFastCGI workers.
Cause: No shared cache backend configured.
Workaround: Fine for a single-worker deployment.
Resolution: Switch CACHES['default'] to Redis for multi-worker deployment.
Open: documentation says qdg, code connects to qdb
Status: Open — documentation defect, not a code bug.
Symptoms: CLAUDE.md and PLAN.md both name the database qdg. config/settings.py
sets DATABASES['default']['NAME'] = 'qdb' — confirmed by reading the file directly.
Cause: Unclear — possibly a rename that wasn't propagated to the docs, or the docs were
written from an earlier/different environment.
Resolution: Update CLAUDE.md/PLAN.md to say qdb, or confirm there's a second qdg
database somewhere that these docs actually mean. Until resolved, trust settings.py. See
[[database-schema]].
Open: Django 5.2.8 (docs/docx) vs Django 6.0.6 (CLAUDE.md)
Status: Open — unverified which is actually installed.
Symptoms: Runner_Form_Project_Documentation.docx and PLAN.md record Django 5.2.8;
CLAUDE.md records 6.0.6.
Resolution: Check the active venv (python -m django --version) and correct whichever doc
is wrong.
Note: two templates exist with no route (meeting_list.html, meeting_detail.html)
Status: Dead or in-progress code, not confirmed which.
Symptoms: runner_form/templates/runner_form/meeting_list.html and meeting_detail.html
exist, and queries.py has a matching get_meeting_details() function with its own cache key
(runner_form:meeting_details:{date}), but no view or URL in urls.py renders them.
Resolution: Confirm with whoever added them whether this is unfinished work-in-progress or
safe to remove.
Note: FEATURES.md / Runner_Form_Features.docx are partly stale
Status: Documentation defect.
Symptoms: Both describe the "Form Guide" page and horse age/description in the header as
not-yet-built. Both are implemented today (/form/guide/, views.form_guide, and
horse.description rendered in detailed-form.html).
Resolution: Re-check remaining FEATURES.md items (extended career stats breakdown by
distance/track/class) against the current templates before treating that file as an accurate
backlog.
Limitation: trial data fields always null
Status: Data limitation, not a code bug.
Symptoms: trial_race.class_level, sot, and time_winner_sec render as — on every
row.
Cause: These columns are NULL for all rows in the current DB.
Resolution: Will resolve automatically once the source data is populated; no template/query
change needed.
Limitation: pre-2021 sectional data (confirmed root cause)
Status: Data limitation, not a code bug — root cause confirmed by direct investigation.
Symptoms: run.vp_1200/800/600/400/200 sectional-position columns are NULL for races
before 2021; the UI shows dashes.
Investigation: A full-table count against run (43,952,078 total rows) found that for the
2015–2020 date range (11,473,723 rows — all of WINX's 43-race career, runner_id 989258) every
vp_* column returns exactly 0. The same query against 2020–2025 shows ~639,000+ rows with
data per column, confirming the data-ingestion pipeline never back-filled sectional data before
roughly 2021.
Workaround: Code falls back to run.pos_1200, run.pos_800, run.pos_turn,
run.pos_settling for older races, and correctly renders — when those are also NULL.
Resolution: Requires the data provider to back-fill historical sectional data into qdb;
no application code changes are needed once that happens.
Limitation: gear_change parsing is string-based
Status: Fragile by design, not currently broken.
Symptoms: gear_change parsing in queries.py relies on human-readable strings
(blinkers, winkers, tongue tie, etc.) mapped via GEAR_MAPPING.
Risk: If the live schema starts storing coded values instead of these strings,
GEAR_MAPPING needs updating. Verify with:
SELECT DISTINCT gear_change FROM run WHERE gear_change IS NOT NULL ORDER BY gear_change;