Skip to content

fix(ts-client): prevent Overview crash from single-resource cache seeding#3048

Open
slvnlrt wants to merge 1 commit intospacedriveapp:spacedrive-datafrom
slvnlrt:fix/overview-crash-single-resource-seeding
Open

fix(ts-client): prevent Overview crash from single-resource cache seeding#3048
slvnlrt wants to merge 1 commit intospacedriveapp:spacedrive-datafrom
slvnlrt:fix/overview-crash-single-resource-seeding

Conversation

@slvnlrt
Copy link
Copy Markdown
Contributor

@slvnlrt slvnlrt commented Mar 28, 2026

Summary

  • updateSingleResource seeded the TanStack cache with { files: [...], total_count, has_more } when oldData was null (buffer replay race). This list-shaped fallback broke single-resource queries like libraries.info where the response is a plain Library object, causing TypeError: Cannot read properties of undefined (reading 'total_capacity') on the Overview page.
  • Returns undefined instead (TanStack no-op) so the queryFn delivers the correct shape. Batch seeding in updateBatchResources is preserved for file listings.

Root Cause

The subscription manager pre-registers the listener before transport.subscribe() (correct for capturing buffer replay). When the daemon has a recent ResourceChanged for library (from recalculate_statistics()), the buffer replay delivers it before the queryFn resolves. With oldData null, the fallback creates { files: [Library] } which has no statistics key, crashing the Overview component.

Why only updateSingleResource

updateBatchResources keeps its { files: [...] } seeding because ResourceChangedBatch events are only emitted by the file indexing pipeline, where the list shape is correct. Single ResourceChanged events affect all resource types (library, device, volume, location, tag), most of which don't use list-shaped responses.

…ding

updateSingleResource seeded the TanStack cache with { files: [...] }
when oldData was null (buffer replay race). This list-shaped fallback
broke single-resource queries like libraries.info where the response
is a plain object, causing TypeError on statistics.total_capacity.

Return undefined instead so the queryFn delivers the correct shape.
Batch seeding in updateBatchResources is preserved for file listings.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

Walkthrough

Modified the cache seeding fallback in useNormalizedQuery to return undefined instead of a list-shaped wrapper object when oldData is absent. This prevents writing incorrect data shapes to the cache when the query function hasn't yet populated initial data.

Changes

Cohort / File(s) Summary
useNormalizedQuery cache logic
packages/ts-client/src/hooks/useNormalizedQuery.ts
Updated updateSingleResource fallback to return undefined instead of { files: resourcesToUpdate, total_count, has_more: false } when oldData is missing, preventing invalid cache state.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A cache that was wrapping too tight,
Now falls back to void when data's not right,
No phantom objects clogging the store,
Just undefined silence—much cleaner than before! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description provides comprehensive context (summary, root cause, design decision) but does not include the required 'Closes #(issue)' reference specified in the template. Add 'Closes #(issue)' line referencing the issue this PR resolves, as specified in the repository's description template.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main fix: preventing an Overview crash caused by incorrect single-resource cache seeding fallback behavior.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@slvnlrt
Copy link
Copy Markdown
Contributor Author

slvnlrt commented Mar 28, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/ts-client/src/hooks/useNormalizedQuery.ts (1)

509-513: Please add a regression test for this cold-cache branch.

Given this behavioral change, add coverage that updateSingleResource leaves cache unset when oldData is missing, while updateBatchResources still seeds list-shaped cache. This will prevent reintroducing the Overview crash pattern.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ts-client/src/hooks/useNormalizedQuery.ts` around lines 509 - 513,
Add a regression test that exercises the cold-cache branch in useNormalizedQuery
by calling updateSingleResource with oldData === undefined and asserting it does
not set the cache, and a separate test that calls updateBatchResources when
oldData is undefined and asserts it still seeds a list-shaped cache;
specifically instantiate the hook (or call the exported helpers) so
updateSingleResource and updateBatchResources are invoked with a missing
oldData, mock or spy on the cache setter to verify no write occurs for
updateSingleResource and that a list-shaped value is written for
updateBatchResources, and include assertions to prevent reintroduction of the
Overview crash pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/ts-client/src/hooks/useNormalizedQuery.ts`:
- Around line 509-513: Add a regression test that exercises the cold-cache
branch in useNormalizedQuery by calling updateSingleResource with oldData ===
undefined and asserting it does not set the cache, and a separate test that
calls updateBatchResources when oldData is undefined and asserts it still seeds
a list-shaped cache; specifically instantiate the hook (or call the exported
helpers) so updateSingleResource and updateBatchResources are invoked with a
missing oldData, mock or spy on the cache setter to verify no write occurs for
updateSingleResource and that a list-shaped value is written for
updateBatchResources, and include assertions to prevent reintroduction of the
Overview crash pattern.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c0a8fa58-d873-4b49-b6ee-c52ee2faf3f8

📥 Commits

Reviewing files that changed from the base of the PR and between f93a34c and dd29857.

📒 Files selected for processing (1)
  • packages/ts-client/src/hooks/useNormalizedQuery.ts

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.

1 participant