Skip to main content

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: loading state initialised to false, causing the Create Webhook button to show before subscriptions loaded
  • Fix: Added separate creating state and initialised loading to true
  • 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:create script
  • 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 @unique from athleteId and 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 WebhookSubscription model with relation to StravaToken
  • Issue: Prisma validation error: "The argument references must refer to a unique criterion in the related model"
  • Investigation: Webhook subscriptions are app-wide, not tied to individual tokens since athleteId is no longer unique
  • Fix: Removed the foreign key relation and made createdByAthlete a simple BigInt? 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) and thumbPng (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) and thumbPng (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.