Skip to content

The culprit frame is listed twice in frames[] #15

Description

@GabrielBBaldez

parseReports returns the culprit twice in frames — once because the culprit is pushed into the list, and once because it is also the top entry of the stack. Both formats do it, and both have since before #13; the JSON path introduced in that PR simply matches the text path.

Reproduce with a file the library repo generates:

const { parseReports } = require("./out/stParser.js");
const fs = require("fs");
const text = fs.readFileSync("<stacktale>/stacktale-core/src/test/resources/golden/repro-report.txt", "utf8");
const r = parseReports(text)[0];
console.log(r.frames.length);                       // 2
r.frames.forEach(f => console.log(f.file + ":" + f.line));
// PaymentService.java:118
// PaymentService.java:118

One distinct location, listed twice. repro-report.txt has a one-frame stack, so the duplicate is the whole list; on a real report it's the first two entries that are identical.

Why it matters

frames drives the navigable list in the panel. A user clicking the first two entries lands in the same place both times and has no way to tell why, which reads as the extension being confused about the stack rather than as a duplicate.

What to change

Drop the frame from the stack when it is the same location the culprit already occupies. Compare on file and line rather than on text — the culprit's text carries a ← YOUR CODE suffix that the stack copy doesn't, so a string comparison silently never matches, which is the trap here.

Keep the culprit as the first entry and drop the stack's copy, not the other way round: the culprit is the one with the marker on it.

How to check it

  • repro-report.txt above goes from 2 frames to 1.
  • The same report in st-json/1 gives the same count as the text form. That equivalence is the actual invariant and is worth an assertion of its own — the two paths are independent code and only a test comparing them will keep them honest.
  • A report whose culprit genuinely isn't the top stack frame (a distilled stack where the culprit sits further down) keeps every frame. Deduping blindly on "first two are equal" would be wrong; the check is culprit-vs-frame, not frame-vs-frame.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions