Skip to content

SCIX-840 fix(vis): prevent author network crash on non-year-prefixed bibcodes#819

Open
thostetler wants to merge 1 commit intoadsabs:masterfrom
thostetler:fix/author-network-error-handling
Open

SCIX-840 fix(vis): prevent author network crash on non-year-prefixed bibcodes#819
thostetler wants to merge 1 commit intoadsabs:masterfrom
thostetler:fix/author-network-error-handling

Conversation

@thostetler
Copy link
Member

@thostetler thostetler commented Mar 4, 2026

  • fix crash when bibcodes don't start with a 4-digit year (parseInt → NaN → range(NaN, NaN) throws)
  • filter NaN from years array, skip groups with no valid years after d3.extent
  • wrap getAuthorNetworkSummaryGraph in try/catch, return { data: [], error } instead of throwing
  • fix container useMemo to return { data: [] } fallback instead of implicit undefined
  • fix SummaryPane to render error message or graph, not both

Bibcodes that don't start with a 4-digit year (e.g. searches like
"potato AND citation_count:20") caused parseInt to return NaN, which
propagated through d3.extent into range(NaN, NaN), throwing a runtime
error that crashed the author network visualization.

- Filter NaN values from years array after parseInt
- Guard against undefined d3.extent result (skip group with no valid years)
- Wrap getAuthorNetworkSummaryGraph body in try/catch, returning { error }
  instead of throwing on unexpected data shapes
- Return data: [] (not undefined) on all error paths to satisfy ILineGraph type
- Fix container useMemo fallback: return { data: [] } when authorNetworkData
  is not yet loaded, preventing undefined being cast to ILineGraph
- Fix SummaryPane: render error message OR graph, not both (error state was
  already shown but LineGraph still rendered with undefined/empty data)
@thostetler thostetler force-pushed the fix/author-network-error-handling branch from 8570444 to da84fcc Compare March 4, 2026 19:50
@thostetler thostetler changed the title fix(vis): prevent author network crash on non-year-prefixed bibcodes SCIX-840 fix(vis): prevent author network crash on non-year-prefixed bibcodes Mar 4, 2026
@thostetler thostetler requested a review from shinyichen March 4, 2026 19:52
@thostetler thostetler marked this pull request as ready for review March 4, 2026 19:53
Copilot AI review requested due to automatic review settings March 4, 2026 19:53
@codecov
Copy link

codecov bot commented Mar 4, 2026

Codecov Report

❌ Patch coverage is 0% with 47 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.9%. Comparing base (a7a0d97) to head (da84fcc).

Files with missing lines Patch % Lines
src/components/Visualizations/utils/graphUtils.ts 0.0% 36 Missing ⚠️
...isualizations/Panes/NetworkDetails/SummaryPane.tsx 0.0% 10 Missing ⚠️
...izations/Containers/AuthorNetworkPageContainer.tsx 0.0% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           master    #819     +/-   ##
========================================
- Coverage    62.0%   61.9%   -0.0%     
========================================
  Files         317     317             
  Lines       36521   36530      +9     
  Branches     1642    1642             
========================================
- Hits        22608   22600      -8     
- Misses      13876   13893     +17     
  Partials       37      37             
Files with missing lines Coverage Δ
...izations/Containers/AuthorNetworkPageContainer.tsx 22.0% <0.0%> (-<0.1%) ⬇️
...isualizations/Panes/NetworkDetails/SummaryPane.tsx 25.9% <0.0%> (-0.8%) ⬇️
src/components/Visualizations/utils/graphUtils.ts 17.9% <0.0%> (-0.1%) ⬇️

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the Author Network “Group Activity Over Time” summary graph generation and rendering to avoid crashes when bibcodes don’t start with a 4-digit year, and to surface errors in the UI instead of throwing.

Changes:

  • Filter invalid years before computing year extents and skip groups with no valid year range.
  • Wrap getAuthorNetworkSummaryGraph in try/catch and return { data: [], error } on failures.
  • Ensure containers/panes render either an error message or the graph (and provide a { data: [] } fallback).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/components/Visualizations/utils/graphUtils.ts Adds NaN filtering + guards for year range and wraps summary graph generation in try/catch.
src/components/Visualizations/Panes/NetworkDetails/SummaryPane.tsx Renders error state or summary line graph (mutually exclusive).
src/components/Visualizations/Containers/AuthorNetworkPageContainer.tsx Ensures the summary graph memo returns a { data: [] } fallback instead of undefined.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +448 to +464
// years range — filter NaN in case bibcodes don't start with a 4-digit year
const years = uniq(bibcodes.map((bibcode) => parseInt(bibcode.slice(0, 4))).filter((y) => !isNaN(y)));
const yearsRange = d3.extent(years);
if (yearsRange[0] === undefined || yearsRange[1] === undefined) {
return;
}
const allYears = range(yearsRange[0], yearsRange[1]); // fill in the years gap

// prefill all years with 0 count values { year: count}
const skeleton: { [year in string]: number } = {};
allYears.forEach((year) => (skeleton[year.toString()] = 0));
// prefill all years with 0 count values { year: count}
const skeleton: { [year in string]: number } = {};
allYears.forEach((year) => (skeleton[year.toString()] = 0));

// into year and paper count array [ ... {year: count} ]
const yearPaperCount = {
...skeleton,
...countBy((bibcode) => bibcode.slice(0, 4), bibcodes),
};
// build yearcount map, merging skeleton with actual bibcode counts
const yearPaperCount = {
...skeleton,
...countBy((bibcode) => bibcode.slice(0, 4), bibcodes),
};
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The years filtering only removes NaN results from parseInt, but parseInt can still return a number for non-4-digit prefixes (e.g. '202A'202). Also, yearPaperCount is built from all bibcodes, so non-year-prefixed bibcodes can still end up as keys (x-values) in graphData, which can break the line graph (especially with xScaleType="linear"). Filter bibcodes up front using a strict 4-digit year check (e.g. /^\d{4}/) and then use that filtered list consistently for both the years/extent computation and the countBy map.

Copilot uses AI. Check for mistakes.
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.

2 participants