fix(district): stop attributing docket uploads to a stale cached case id - #428
Conversation
d45fdb8 to
ba60de0
Compare
The docket report upload fell back to the per-tab cached pacer_case_id when the page context (url, inputs, referrer) yielded none. That cached id can belong to a different case viewed earlier in the same tab, and a docket sheet uploaded under another case's id merges one case's entire history into the other's archive docket. Observed in the wild: all ~165 entries of nvd 3:25-cv-00553 were merged into nvd 2:26-cv-00720 (CourtListener docket 72456248), including the other case's parties. Before reaching for the cached id, derive the case id from the page itself: a district docket sheet carries its own case id in every document link's goDLS() onclick handler. Use the strict majority of those ids, so a stray link to another case's document (legitimate on consolidated/MDL sheets) cannot outvote the sheet, and treat a tie as no evidence. When the page id beats a conflicting cached id, warn on the console and correct the cached id so later caseless pages in the tab (e.g. attachment menus) inherit the right one. An id the page context already provided is never overridden: on consolidated member dockets the document links legitimately point at the lead case, so the goDLS majority only speaks when nothing else does. Pages with no goDLS evidence behave exactly as before.
ba60de0 to
34b7fc6
Compare
ERosendo
left a comment
There was a problem hiding this comment.
Thanks for putting this together! it's a nice improvement, and it should address the stale cache issue from freelawproject/courtlistener#5247.
I left a few small suggestions, mostly around hardening and documentation, but I think the overall approach looks great.
Adopt the reviewer-suggested shape for getCaseIdFromDocketDisplayLinks: count links per case id, sort the counts descending, then compare the top two counts to detect a tie. Behavior is unchanged (single candidate returns it, tie for first returns undefined, no evidence returns undefined) - the single-pass tally-with-tie-flag just took more effort to follow than the problem deserved. Addresses review: freelawproject#428 (comment) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The doc comment claimed a strict majority, but the code returns the
most common case id - {A: 3, B: 2, C: 2} returns A with 3 of 7 links.
Use the reviewer's wording, and align the one other comment that said
majority. Comments only, no behavior change.
Addresses review: freelawproject#428 (comment)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The comment credited the write with helping attachment menus, but attachment menus resolve their case id through the docsToCases map (getPacerCaseIdFromPacerDocId), not the tab's cached caseId. What the write really does is seed the correct id for a later docket-report load in the same tab. Comment only, no behavior change. Addresses review: freelawproject#428 (comment) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
getItemsFromStorage returns undefined for a fresh tab, so navigating
directly to a docket report in a new tab would throw on
tabStorage.caseId. Default to {} like the guarded reads elsewhere
(utils.js). The same unguarded read predates this branch, but this is
the right place to fix it.
Addresses review: freelawproject#428 (comment)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@ERosendo Thanks for the review! All four suggestions are in, one commit each: your rewrite of |
|
Another one of these: https://www.courtlistener.com/docket/63890699/american-civil-liberties-union-v-united-states-immigration-and-customs/ |
|
Thanks Margo. Can you please take a look, Eduardo? |
|
Thanks @MargoSchlanger! The reported case has been cleaned up. |
What this fixes
When a district docket report page yields no case id from its own context (URL, inputs, referrer),
handleDocketDisplayPagefalls back to the per-tab cached case id and uploads the entire page HTML under it. That cached value can belong to a different case viewed earlier in the same tab — nothing invalidates it on navigation — so one case's full docket sheet gets uploaded under another case'spacer_case_id, and the archive faithfully merges one case's entire history (entries and parties) into the other's docket.Real-world occurrence
This happened to a pro se litigant's case in D. Nev.: the complete docket of Empire Trust v. Cellura (nvd
3:25-cv-00553, pacer_case_id177277) was uploaded under Mitchell v. Tate's id (nvd2:26-cv-00720, pacer_case_id180126). CourtListener docket72456248now contains ~165 entries byte-identical (same entry numbers, dates, text, andpacer_doc_ids) to entries on docket71566874, including the foreign case's SDNY pre-transfer history and two of its parties. Both CL docket records carry correct, distinctpacer_case_ids, so the wrong id had to be attached client-side at upload time. A data-repair request for that docket was sent separately via the CourtListener contact form.The fix
Before reaching for the cached id, derive the case id from the page itself: a district docket sheet carries its own case id in every document link's
goDLS()onclick handler. New helperPACER.getCaseIdFromDocketDisplayLinks()tallies those ids, and the fallback path inhandleDocketDisplayPagenow prefers that evidence over the tab cache:findAndStorePacerDocIdsnotes this corner case) — cannot outvote the sheet itself.Tests
Five new specs in
ContentDelegateSpec.js:Full suite: 188/188 passing (183 pre-existing + 5 new).
CHANGES.mdupdated under Upcoming → Fixes.Review round 1 (@ERosendo)
All four suggestions adopted, one commit each: the sort-based rewrite of
getCaseIdFromDocketDisplayLinks, the plurality (not strict-majority) doc wording, the corrected comment on what the tab-storage write feeds (a later docket-report load — attachment menus resolve viadocsToCases, verified), and the|| {}guard ongetItemsFromStoragewith the regression spec above.