Skip to content

Restore import data-loss fixes that never landed on master - #75

Merged
taurheim merged 2 commits into
masterfrom
fix/import-data-loss-on-master
Jul 29, 2026
Merged

Restore import data-loss fixes that never landed on master#75
taurheim merged 2 commits into
masterfrom
fix/import-data-loss-on-master

Conversation

@taurheim

Copy link
Copy Markdown
Owner

PR #73 was merged into a branch that had already been merged, so its fixes never reached master. This restores them.

fix/import-data-loss targeted fix/scrobble-timestamp-collapse (PR #72). #72 merged to master first, capturing its branch head at cce7b82. #73 then merged into that now-stale branch, producing 589e9ea — which is not an ancestor of master:

$ git merge-base --is-ancestor 589e9ea origin/master
NO - NOT on master

$ git grep -c trackDurationCache origin/master -- src/api/LastFm.ts
(no matches)

Both PRs show as merged, so this is easy to miss. That is the failure mode of stacking, and it was my call to stack them — apologies.

This branch cherry-picks 874dba3 onto master. The result is byte-identical to the stranded merged state:

$ git diff 589e9ea HEAD --stat
(empty)

Content is unchanged from what was reviewed and approved in #73: NaN durations no longer discarding plays, per-track duration caching, integer timestamps, and one bad history file no longer aborting the whole import.

taurheim and others added 2 commits July 26, 2026 18:34
Four separate defects found by grouping scrobblify_error events in
PostHog and tracing each back through the import path.

1. A track whose Last.fm entry has a missing, empty or non-numeric
   duration was silently thrown away. parseInt returned NaN, and because
   every comparison against NaN is false it slipped past the "pretend
   it is 2 minutes" fallback *and* the minimum-length check, only to
   fail msListened > NaN at the end. The stated intent of that code is
   to err on the side of giving the user the scrobble.

2. Track durations were looked up once per *play* rather than once per
   distinct track, each with 250ms of enforced rate buffer. A listening
   history is mostly repeat plays, so this multiplied validation time by
   the user's average play count. Now cached per (artist, track),
   including permanent "not found" answers; rate limits and network
   errors stay uncached.

3. user.getrecenttracks was sent fractional timestamps
   (from=1784563202.848). Last.fm documents UNIX timestamps. Same class
   of bug as the one already fixed for track.scrobble. Window ends now
   round outwards, so a duplicate check can only ever look too far,
   never miss.

4. One unreadable or malformed history file abandoned the entire
   import. Large exports genuinely do come back truncated or corrupted
   on memory-constrained mobile browsers, seen across three users.
   Damaged files are now skipped with a visible warning and the rest is
   imported; only a ZIP where every file fails is an error.

Each of the five new tests was confirmed to fail with the source changes
stashed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f0df23dc-ed73-4b56-9b7c-4d2846ddf2a2
@taurheim
taurheim merged commit b1db065 into master Jul 29, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant