Skip to content

fix: Fix duplicate key error on trace viewer ticks#2650

Closed
pulpdrew wants to merge 1 commit into
mainfrom
drew/trace-viewer-tick-key
Closed

fix: Fix duplicate key error on trace viewer ticks#2650
pulpdrew wants to merge 1 commit into
mainfrom
drew/trace-viewer-tick-key

Conversation

@pulpdrew

@pulpdrew pulpdrew commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR fixes a duplicate key error logged by react for the trace minimap when multiple time ticks rounded to the same label. The key is now the unique val instead of the rounded value.

Screenshots or video

Before

Duplicate ticks:

Screenshot 2026-07-15 at 1 15 56 PM

Duplicate key errors:

Screenshot 2026-07-15 at 12 02 03 PM

After

None of the same warnings

Screenshot 2026-07-15 at 12 14 51 PM

How to test on local

Lookup trace id: 75f6402fba79e0c0501bd07191530342 and show logs only. The warning won't appear in the preview environment because it's a prod build.

References

  • Linear Issue:
  • Related PRs:

@vercel

vercel Bot commented Jul 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview, Comment Jul 15, 2026 4:06pm
hyperdx-storybook Ready Ready Preview, Comment Jul 15, 2026 4:06pm

Request Review

@changeset-bot

changeset-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7bd23e7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/app Patch
@hyperdx/api Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

Copy link
Copy Markdown
Contributor

🔵 Tier 2 — Low Risk

Small, isolated change with no API route or data model modifications.

Why this tier:

  • Standard feature/fix — introduces new logic or modifies core functionality

Review process: AI review + quick human skim (target: 5–15 min). Reviewer validates AI assessment and checks for domain-specific concerns.
SLA: Resolve within 4 business hours.

Stats
  • Production files changed: 1
  • Production lines changed: 6
  • Branch: drew/trace-viewer-tick-key
  • Author: pulpdrew

To override this classification, remove the review/tier-2 label and apply a different review/tier-* label. Manual overrides are preserved on subsequent pushes.

@greptile-apps

greptile-apps Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a React duplicate-key warning in the trace viewer's minimap tick rendering by replacing the label string (which can collide after renderMs rounding) with the raw numeric val as the React key.

  • The ticks memo now includes val in each entry, and the JSX map uses key={val} instead of key={label}. Since val = i * interval with a strictly-incrementing i, each tick's value is guaranteed unique, eliminating the duplicate-key error.
  • A changeset entry (patch) is added for the @hyperdx/app package.

Confidence Score: 5/5

Safe to merge — the change is a minimal, targeted fix with no side effects on rendering logic or state.

The only modification is swapping the React key from the rounded display string label to the raw numeric val, which is always unique. The tick data shape gains one extra field but no rendering behaviour or logic changes. The fix is correct and complete.

No files require special attention.

Important Files Changed

Filename Overview
packages/app/src/components/TimelineChart/TimelineMinimap.tsx Adds val to tick objects and uses it as the React key instead of label, correctly fixing the duplicate-key error when ticks round to the same display string.
.changeset/eighty-planets-mate.md New changeset entry marking a patch release for the app package.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["useMemo: compute ticks"] --> B["for i = 0, 1, 2, ..."]
    B --> C["val = i * interval (unique)"]
    C --> D["frac = val / maxVal"]
    D --> E["label = renderMs(val)\n(may collide for nearby vals)"]
    E --> F["push { val, frac, label }"]
    F --> G{"frac > 1?"}
    G -- No --> B
    G -- Yes --> H["return ticks array"]
    H --> I["ticks.map(({ val, frac, label }))\nkey=val ✅ (was key=label ❌)"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["useMemo: compute ticks"] --> B["for i = 0, 1, 2, ..."]
    B --> C["val = i * interval (unique)"]
    C --> D["frac = val / maxVal"]
    D --> E["label = renderMs(val)\n(may collide for nearby vals)"]
    E --> F["push { val, frac, label }"]
    F --> G{"frac > 1?"}
    G -- No --> B
    G -- Yes --> H["return ticks array"]
    H --> I["ticks.map(({ val, frac, label }))\nkey=val ✅ (was key=label ❌)"]
Loading

Reviews (1): Last reviewed commit: "fix: Fix duplicate key error on trace vi..." | Re-trigger Greptile

@github-actions

Copy link
Copy Markdown
Contributor

Deep Review

✅ No critical issues found.

This is a minimal, correct fix. renderMs(val) rounds distinct tick values to the same string, so keying the rendered ticks on label collided; the diff adds the numeric val to each tick object (TimelineMinimap.tsx:116) and keys on it instead. Since val = i * interval with interval > 0 (guarded by maxVal > 0) is strictly increasing, every tick receives a unique key, and the numeric key is valid because React coerces it to a string. No correctness, type-safety, or behavior regression was found.

🔵 P3 nitpicks (2)
  • packages/app/src/components/TimelineChart/TimelineMinimap.tsx:116 — A render harness (TimelineMinimap.test.tsx) exists but no test guards the key-collision scenario, so a future revert to keying on label would go uncaught.
    • Fix: Add a render case whose maxVal yields distinct vals that renderMs rounds to the same label, then assert no duplicate-key console.error fires and the rendered tick count matches the tick array length.
  • packages/app/src/components/TimelineChart/TimelineMinimap.tsx:279 — The reason for keying on val rather than the human-readable label is non-obvious to a future reader.
    • Fix: Add a one-line comment noting that renderMs labels can collide after rounding and must not be used as React keys.

Reviewers (4): correctness, testing, maintainability, kieran-typescript.

Testing gaps: The behavioral change (React key derived from val instead of label) is not exercised by any test; the collision it fixes depends on renderMs rounding distinct values to the same string.

@github-actions

Copy link
Copy Markdown
Contributor

E2E Test Results

All tests passed • 237 passed • 3 skipped • 1539s

Status Count
✅ Passed 237
❌ Failed 0
⚠️ Flaky 1
⏭️ Skipped 3

Tests ran across 4 shards in parallel.

View full report →

@pulpdrew

Copy link
Copy Markdown
Contributor Author

Closing in favor of #2652

@kodiakhq kodiakhq Bot closed this in #2652 Jul 16, 2026
govtech42 pushed a commit to forks-ai/hyperdx that referenced this pull request Jul 16, 2026
…bels (hyperdxio#2652)

 # Summary

On the trace minimap and waterfall viewer, short traces (or traces zoomed in far enough) produced duplicate tick values for values that rounded to the same ms value. Now, we ensure that adjacent tick labels differ by adding precision when adjacent values would round to the same number.

## What changed

- Trace viewer and trace minimap tick labels now show just enough precision to ensure that adjacent values are different
- The trace viewer cursor / tooltip displays precision matching the tick labels

### Before

https://github.com/user-attachments/assets/dd4cbcf2-495c-4b72-b4fc-b5476e78fae9

<img width="1079" height="439" alt="Screenshot 2026-07-16 at 8 45 27 AM" src="https://github.com/user-attachments/assets/8ba7bb1d-acd8-44f0-9a29-5b363ffe1dc8" />


### After

https://github.com/user-attachments/assets/a4a514eb-9593-46f7-99ab-69d37f682545

<img width="1057" height="360" alt="Screenshot 2026-07-16 at 8 45 19 AM" src="https://github.com/user-attachments/assets/4f9838b4-d2ab-434c-8d5e-b1a459681640" />

## How to test in Preview

Pick a relatively short trace and zoom way in. Observe the trace viewer ticks and cursor/tooltip.

## References

Closes HDX-4803
Closes hyperdxio#2650
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review/tier-2 Low risk — AI review + quick human skim

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants