Bug report: Garmin Connect FIT course import creates corrupt courses ("Invalid course" on device)

# Bug report: Garmin Connect FIT course import creates corrupt courses ("Invalid course" on device)

**First observed:** 2026-07-04 (evening, CEST)

**Re-confirmed:** 2026-07-10, on freshly updated Edge firmware, via the iOS Garmin Connect app

**Device:** Garmin Edge 1040 (Dutch UI), synced via Garmin Connect

**Where to file:** Garmin support / forums.garmin.com → Garmin Connect Web (also affects the iOS app import path)

## Summary

Importing ANY course FIT file via Garmin Connect — web (Training & Planning →

Courses → Import) **and** the iOS Garmin Connect app — produces a course object

that syncs to the Edge 1040 but fails to open with

**"Ongeldige koers. Wissen?"** ("Invalid course. Delete?").

This includes a course FIT file **exported by Garmin Connect itself**

Garmin Connect cannot re-import its own export. The imported course renders

normally in the GC phone app (map, course points all visible); only the device

rejects it.

The same import path worked on 2026-05-24 (course imported then still opens

fine today). The regression window is therefore **late May – early July 2026**,

and it persists as of 2026-07-10.

## Evidence matrix

### Round 1 — 2026-07-04, GC web import, Edge 1040

| Test | Result |

|---|---|

| Send EXISTING course (created 2026-05-24 via FIT import, 173 course points) to device | White check mark opens fine |

| Import GC's own exported FIT of that same course (`COURSE_465831776.fit`) as new course → send | X "Ongeldige koers" |

| Import GC's own export of another course (`Corvara-losrijden.fit`, exported 2026-06-30) → send | X "Ongeldige koers" |

| Import third-party course FIT (validated clean by garmin-fit-sdk `check_integrity()`) → send | X "Ongeldige koers" |

| Import the same course as **TCX** → send | White check mark opens (course points stripped, as usual) |

| Device reboot, deleting all courses on device + in GC, clean re-sync | X no change |

| Old courses already on device | White check mark all open fine |

### Round 2 — 2026-07-10, iOS Garmin Connect app import, Edge 1040 on freshly updated firmware

Device software was updated to the latest available version immediately before

this round, ruling out stale-firmware causes.

| Test | Result |

|---|---|

| Import `GFNY_Grand_Ballon_Long.fit`**Garmin Connect's own export** (file_id: manufacturer=garmin, garmin_product=connect) → sync → open | X "Ongeldige koers" |

| Import third-party course FIT variant A (structure matching the 2026-05-24 working import: 12-byte header, cues appended) → sync → open | X "Ongeldige koers" |

| Import third-party course FIT variant B (FIT-Cookbook-conformant: 14-byte header + CRC, timer events, interleaved course points, 50 cues) → sync → open | X "Ongeldige koers" |

| Courses imported before the regression (May 2026) | White check mark still open fine |

Both third-party variants decode cleanly (fitparse; monotonic distance and

timestamps, course points in-bounds and interleaved, valid course-point types).

Their acceptance is irrelevant to the conclusion, however — **Garmin's own

export failing its own re-import** isolates the fault to the import pipeline

regardless of any third-party encoding choices.

## Conclusion

- Device is fine (old courses + newly *sent* existing course objects open; fresh firmware).

- Transport is fine (existing course objects deliver and open).

- TCX import path is fine (different parser).

- The file contents are irrelevant (Garmin's own export fails; spec-conformant

  and legacy-shaped third-party files fail identically).

- **The FIT course import pipeline (web + iOS app) creates corrupt course

  objects in the Garmin Connect database.** The GC app renders them fine

  (lenient map view); the device's stricter course validator rejects the FIT

  that GC's sync encoder regenerates from the corrupted object.

- Regression introduced between 2026-05-24 (last known-good import) and

  2026-07-04; still present 2026-07-10.

## Impact

- Rider could not load a race course with nutrition/pacing course points onto

  the Edge 1040 the night before Maratona dles Dolomites (2026-07-05).

- Recurred 2026-07-09/10 preparing GFNY Grand Ballon: course imports, shows

  all course points in the GC app, and is rejected by the device.

- Affects every Edge user importing FIT courses (including files exported from

  Garmin Connect itself); workarounds (TCX) strip course points.

## Reproduction (any account, ~5 minutes)

1. Export any existing, working course from Garmin Connect as FIT.

2. Re-import that same file as a new course (web or iOS app).

3. Send the new course to an Edge; open it on the device → "Invalid course. Delete?"

## Attachments to include

- `COURSE_465831776.fit` — GC's own export that GC's import corrupts (Desktop)

- `Corvara-losrijden.fit` — second GC-native example (Trash / re-export from GC)

- `GFNY_Grand_Ballon_Long.fit` — third GC-native example (Desktop), fails via iOS app import 2026-07-10