Fix nine formatters that read field paths the API never returns - #25
Merged
Merged
Conversation
Every tool in this commit called its endpoint correctly and reported success.
What they got wrong was the *shape* of the reply, so they rendered "undefined"
-- or, worse, silently rendered nothing and looked fine.
`contentClient.get<T>` asserts T, it does not verify it, so nothing caught any
of this. Each fix is pinned by a test built from a payload copied verbatim off
the live services.
Crashed or printed "undefined":
- search_suggest / search_spellcheck: both endpoints return a bare array of
strings, not `{suggestions: [...]}`. Suggest threw on `.map`; spellcheck
guarded the access and so reported "no suggestions" for every input.
- entity_component_of: entries are one per relationship type, carrying
parallel `names`/`stIds`/`schemaClasses` arrays -- not Complex objects.
Every container printed "**undefined** (undefined) [undefined]", and the
total counted relationship types rather than containers.
- participants: the endpoint returns a reduced projection keyed on `peDbId`,
with no `stId` and no `dbId`.
- static_interactors / psicquic_details: `entities` lists the molecules
queried; the interactors hang off each one. Reading score a level too high
threw "Cannot read properties of undefined (reading 'toFixed')".
- interactor_summary / psicquic_summary: same envelope, same level error.
- analysis_found_entities: a mapsTo entry has `ids` (plural), not
`identifier`.
Silently dropped data, with no "undefined" to give it away:
- participants never showed external identifiers: the endpoint returns
`refEntities` (an array), never a singular `referenceEntity`. UniProt
accessions are now rendered.
- search_facets returned nothing but its heading. Each facet is an object
with an `available` list, so `.length` was undefined and every section was
skipped as falsy.
Also:
- events_hierarchy defaulted to species "Homo sapiens", which that endpoint
answers with HTTP 500; "9606" returns 200. The default made the tool fail
every time it was called without an explicit species.
- The four interactor tools shared one envelope and four wrong copies of it.
They now share one type and one formatter.
Found by sweeping every reachable tool against the live services and diffing
rendered output against the real payloads. 41 tests -> 57; 15 of the 16 new
tests fail against the previous code.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Nine tools called their endpoint correctly and reported success, but read fields the Reactome APIs never return. They rendered
undefined— or, worse, silently rendered nothing and looked fine.contentClient.get<T>assertsT, it does not verify it, so nothing caught any of this. The seven analysis tools had no tests at all, which is why the token bug fixed in #21 survived as long as it did.Crashed or printed "undefined"
search_suggest,search_spellcheckstring[], not{suggestions: []}. Suggest threw on.map; spellcheck guarded the access, so it reported "no suggestions" for every inputentity_component_ofnames/stIds/schemaClassesarrays — notComplexobjects. Every container printed**undefined** (undefined) [undefined]participantspeDbId; nostId, nodbIdstatic_interactors,psicquic_detailsentitieslists the molecules queried; interactors hang off each one. Readingscorea level too high threwCannot read properties of undefined (reading 'toFixed')interactor_summary,psicquic_summaryanalysis_found_entitiesmapsToentry hasids(plural), notidentifierSilently dropped data, with no "undefined" to give it away
participantsnever showed external identifiers — the endpoint returnsrefEntities(an array), never a singularreferenceEntity. UniProt accessions are now rendered, which is new capability, not just cosmetics.search_facetsreturned nothing but its heading. Each facet is an object with anavailablelist, so.lengthwasundefinedand every section was skipped as falsy.These two are the reason this PR is bigger than the sweep that started it: grepping rendered output for
undefinedcannot find a field that was dropped cleanly. Only diffing against the real payload does.Also
events_hierarchydefaulted to species"Homo sapiens", which that endpoint answers with HTTP 500;"9606"returns 200. The default made the tool fail every time it was called without an explicit species.How it was found
Swept every reachable tool against the live services — 48 of 53, once a real analysis token was obtained to unlock the token-gated ones — and diffed rendered output against the actual payloads.
Verification
npm test: 41 → 57 tests, all passing.src/).undefinedin any rendered output.Known upstream, not fixed here
/data/orthology/{id}/species/{taxId}returns HTTP 500 for valid-looking input, and/interactors/psicquic/molecule/{resource}/...returns 500 rather than 400 for an unknown resource. Both are Reactome-side; our URLs match the documented routes.🤖 Generated with Claude Code