Skip to content

fix(mods): guard readModDetail against a missing releases array - #210

Merged
Zaldaryon merged 1 commit into
devfrom
fix/moddb-releases-guard
Aug 22, 2026
Merged

fix(mods): guard readModDetail against a missing releases array#210
Zaldaryon merged 1 commit into
devfrom
fix/moddb-releases-guard

Conversation

@Zaldaryon

@Zaldaryon Zaldaryon commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

A mod detail response whose mod object has no releases array crashed the Install Mod popup with TypeError: Cannot read properties of undefined (reading 'map'), because readModDetail only validated modid and name. The reader now rejects that shape up front, so the response flows through the existing malformed-response failure path and the popup shows its failure state instead of crashing.

The same guard also protects useGetCompleteInstalledMods, which iterates dmod.releases directly and would have hit the same crash for installed-mod details missing the field.

Two unit tests cover the new cases: a detail with no releases key, and one where releases is not an array. Both assert the malformed-response result like their sibling tests.

Type

  • Bug fix
  • Feature
  • Performance
  • Refactor or cleanup
  • Tests only
  • Docs or build

Checklist

  • Targets dev, not main.
  • npm run typecheck passes.
  • npm run lint:ci passes.
  • npm run format:check passes.
  • npm run test:coverage passes, coverage at or above the floor in vitest.config.ts.
  • npm run build:unpack passes.

As with #205, build:unpack was left to CI; this touches one guard and two tests. Happy to run it locally if reviewers prefer.

Testing

Ran on node v22.22.1 with the repo's TypeScript 5.9.2 (Linux node_modules, so commands ran under WSL):

  • npm run typecheck: clean across node, web, and tests configs.
  • npm run lint:ci: 0 errors; 15 warnings, all pre-existing exhaustive-deps findings in untouched files.
  • npm run format:check: pass.
  • Targeted vitest run tests/domain/mods/moddb.test.ts: 24 passed, including the two new cases.

Manual trace: a detail payload without releases now reaches InstallModPopup's failure UI with the reload button, instead of throwing at line 103.

Related issues

Fixes #199

The install popup and the installed-mods scan both map or iterate releases directly, so a detail response without the array crashed them instead of reaching their failure states.
@Zaldaryon
Zaldaryon requested a review from Pixnop August 22, 2026 12:12

@Pixnop Pixnop left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approving. The guard sits at the right layer: readModDetail is the single door every consumer comes through, so one check there covers the install popup and useGetCompleteInstalledMods (which iterates dmod.releases directly and would have crashed the same way), instead of a guard per caller. The comment earns its place by saying why this field gets an explicit check when modid and name do not: the API is not known to always send it.

Both new rows assert the malformed-response shape like their siblings, and the mutation is obvious enough that I did not need to run it: delete the Array.isArray line and both rows return a parsed detail instead of the refusal.

Coordination note, my fault not yours: I had an agent picking up #199 alongside #200 and #201 from the same review batch. I have pulled #199 out of its scope, so the branch coming for those two will not touch moddb.ts. Yours lands first.

@Zaldaryon
Zaldaryon merged commit 2bee074 into dev Aug 22, 2026
7 checks passed
@Zaldaryon
Zaldaryon deleted the fix/moddb-releases-guard branch August 22, 2026 12:24
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