Debug diary
This document captures the major debugging sessions, errors, and fixes applied during development.
Structure
- Date — When the debugging happened.
- Context — What was being worked on.
- Issue — What broke or didn't work as expected.
- Investigation — Steps taken to understand the issue.
- Fix — What was changed to solve it.
- Lesson — Key takeaway for future work.
Debug fix history
note
Expand each fix for more details.
September 2025
Webhook admin modal "Creating..." flash
- Context: Webhook admin modal UI
- Issue: Brief "Creating..." flash when opening subscription modal
- Investigation:
loadingstate initialised tofalse, causing theCreate Webhookbutton to show before subscriptions loaded - Fix: Added separate
creatingstate and initialisedloadingtotrue - Lesson: UI loading states need careful initialisation to prevent unwanted flashes
Split distance display bug
- Context: Split data display on activities page
- Issue: User reported "its not showing 0.08 its showing 83 - with the column in km"
- Investigation: Display logic switched between km and metres based on a distance threshold
- Fix: Changed from conditional display
split.distanceKm >= 1.0 ? split.distanceKm.toFixed(2) : (split.distanceKm * 1000).toFixed(0)to always show km:split.distanceKm.toFixed(2) - Lesson: Keep distance units consistent rather than switching based on thresholds
Webhook Script Token Error
- Context: Running
npm run webhook:createscript - Issue: Script failed with "No STRAVA_ACCESS_TOKEN environment variable found"
- Investigation: Script runs in a separate process and needs the token explicitly, not from the web session
- Fix: Retrieve the token from the database and set the environment variable manually for the script
- Lesson: Background scripts need explicit token configuration and cannot inherit from web sessions
Strava Webhook Verification Failure
- Context: Creating Strava webhook subscription
- Issue: Webhook creation failed with "GET to callback URL does not return 200" despite manual curl working
- Investigation: Added logging to the webhook handler, tested with curl, and monitored server logs during creation attempts
- Fix: Firewall was blocking Strava webhook IP addresses; added IP whitelist rules
- Lesson: Webhook verification failures are often due to network or firewall issues, not code problems
Prisma Unique Constraint Error
- Context: Implementing audit trail for Strava tokens
- Issue:
prisma.stravaToken.create()failed with "Unique constraint failed on the fields: (athleteId)" - Investigation: Audit trail requires multiple token records per athlete, but the unique constraint prevented this
- Fix: Removed
@uniquefromathleteIdand added@@index([athleteId, isActive])for efficient queries - Lesson: Audit trails require removing unique constraints and using composite indexes
Webhook Foreign Key Constraint Error
- Context: Adding
WebhookSubscriptionmodel with relation toStravaToken - Issue: Prisma validation error: "The argument
referencesmust refer to a unique criterion in the related model" - Investigation: Webhook subscriptions are app-wide, not tied to individual tokens since
athleteIdis no longer unique - Fix: Removed the foreign key relation and made
createdByAthletea simpleBigInt?field - Lesson: App-wide resources like webhooks should not have direct FKs to user-specific records when uniqueness is not guaranteed
Performance Issues - Heavy Database Fields
- Context: Main page loading extremely slowly
- Issue: API responses taking several seconds with huge payload sizes
- Investigation: Found
raw(MB of JSON) andthumbPng(base64 images) included in API responses - Fix: Excluded heavy fields from API responses and used explicit field selection in queries
- Lesson: Always exclude heavy fields from list endpoints; response size matters more than convenience
Main Page Map Request Overload
- Context: Performance optimisation of main activity page
- Issue: Page made 40+ map requests on load, causing slow performance
- Investigation: Eager map prefetching was enabled for every activity thumbnail
- Fix: Removed eager prefetching and implemented lazy loading with the Intersection Observer API
- Lesson: Eager loading can become anti-optimisation at scale; lazy load non-critical resources
Webhook Cache Inconsistency
- Context: Webhook subscription management
- Issue: Deleting a webhook from the Strava API did not update the local database cache
- Investigation: Disconnect process removed the remote webhook but left a stale cache entry
- Fix: Modified the disconnect route to call
cacheWebhookDeleted()for each removed subscription - Lesson: Cache invalidation must happen wherever data changes, not just in primary update paths
Major issues resolved categories
Performance issues
- Large Database Fields: Fixed accidental inclusion of
raw(MB of JSON) andthumbPng(base64 images) in API responses. - Slow Page Loads: Reduced response times from several seconds to <50ms.
- Database Queries: Optimized with specific field selection and proper indexing.
Data accuracy issues
- Fastest Pace Calculations: Fixed incorrect fastest pace values by recalculating from splits data.
- Missing Conditional Fields: Properly handle null values for HR, cadence, and other optional metrics.
- Pace Formatting: Consistent MM:SS/km format across all displays.
UI/UX issues
- Tailwind CSS v4 Configuration: Fixed PostCSS setup for proper CSS compilation.
- Mobile Responsiveness: Implemented mobile-first design with optimized spacing.
- One-tap navigation: Made entire activity rows clickable for better mobile UX.
- Space optimisation: Full-width tiles with minimal gaps, removed redundant elements.
- Clean interface: Removed avg HR from main list, streamlined activity cards.
- Interactive elements: Simplified navigation by removing overlapping click targets.
Authentication and sync issues
- Token Persistence: Implemented database-first token storage for background workers.
- Automatic Refresh: Background worker refreshes tokens every 4 hours.
- Cross-Process Communication: Workers share authentication state seamlessly.
- Unified Token Management: Fixed browser/worker token synchronisation issues.
- Cross-Device Authentication: Solved Safari iPhone + Chrome Mac authentication problems.
- Database-first Architecture: Moved from file-based fallbacks to pure database architecture.