Fix file-properties cachedFile race crash on file switch #154

Closed
opened 2026-05-30 20:57:15 +00:00 by steve · 0 comments
Owner

The file properties side panel throws when switching notes quickly because an async
callback reads cachedFile.hash after the active file has changed.

Problem

file-properties.svelte guards on cachedFile?.hash synchronously, then reads
cachedFile.hash inside tick().then(() => setTimeout(...)). When the user
switches files before the callback runs, cachedFile is undefined and the panel
crashes with Cannot read properties of undefined (reading 'hash').

Goal

Load frontmatter synchronously from the metadata cache without async races.

Scope

  • Replace the async $effect with $derived.by using app.metadataCache.getCache(path)
  • Remove unused cachedFile, tick, and mutable $state for frontmatter

Non-goals

  • Refactoring other frontmatter surfaces
  • Spec changes (behavior unchanged aside from crash fix)

Acceptance Criteria

  • Rapid file switching with the file properties panel open does not throw
  • Frontmatter tracks the active file and updates when cache changes
  • pnpm --filter @lapis-notes/plugin-markdown check:all passes

Implementation Notes

Use the same cache lookup API as outline.svelte (getCache(path)).

Suggested Files or Specs To Inspect

  • packages/plugins/plugin-markdown/src/lib/views/file-properties/file-properties.svelte
  • packages/plugins/plugin-markdown/src/lib/views/outline/outline.svelte

Validation Commands

pnpm --filter @lapis-notes/plugin-markdown check:all

Follow-up Tasks

Implementation Summary

Replaced async cachedFile hash lookup in file-properties.svelte with synchronous $derived.by using metadataCache.getCache(path). Eliminates race when switching files while the panel is open. Validated with pnpm --filter @lapis-notes/markdown check:all and check:svelte.

The file properties side panel throws when switching notes quickly because an async callback reads `cachedFile.hash` after the active file has changed. ## Problem `file-properties.svelte` guards on `cachedFile?.hash` synchronously, then reads `cachedFile.hash` inside `tick().then(() => setTimeout(...))`. When the user switches files before the callback runs, `cachedFile` is undefined and the panel crashes with `Cannot read properties of undefined (reading 'hash')`. ## Goal Load frontmatter synchronously from the metadata cache without async races. ## Scope - Replace the async `$effect` with `$derived.by` using `app.metadataCache.getCache(path)` - Remove unused `cachedFile`, `tick`, and mutable `$state` for frontmatter ## Non-goals - Refactoring other frontmatter surfaces - Spec changes (behavior unchanged aside from crash fix) ## Acceptance Criteria - Rapid file switching with the file properties panel open does not throw - Frontmatter tracks the active file and updates when cache changes - `pnpm --filter @lapis-notes/plugin-markdown check:all` passes ## Implementation Notes Use the same cache lookup API as `outline.svelte` (`getCache(path)`). ## Suggested Files or Specs To Inspect - `packages/plugins/plugin-markdown/src/lib/views/file-properties/file-properties.svelte` - `packages/plugins/plugin-markdown/src/lib/views/outline/outline.svelte` ## Validation Commands ```bash pnpm --filter @lapis-notes/plugin-markdown check:all ``` ## Related Issues - Follow-up to #65 — [Harden note-local frontmatter value editing and write semantics](../closed/65-harden-note-local-frontmatter-value-editing-and-write-semantics.md) ## Follow-up Tasks ## Implementation Summary Replaced async cachedFile hash lookup in file-properties.svelte with synchronous $derived.by using metadataCache.getCache(path). Eliminates race when switching files while the panel is open. Validated with pnpm --filter @lapis-notes/markdown check:all and check:svelte. <!-- backlog:task_id=TASK-PLUGIN-FILE-PROPS-RACE source_spec=spec/src/20-packages/plugins/markdown/index.md related_issue=65 -->
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lapis-notes/lapis#154
No description provided.