Skip to content

Tab shows "Loading..." forever when a file read blocks; reopening the file never retries #23

Description

@anbturki

Summary

A tab's loading state is cleared only when the readTextFile promise settles. The Rust side performs a synchronous read_to_end inside the async command, so a file whose OS-level read blocks (iCloud/Dropbox online-only placeholder that needs to download, hung network mount, TCC consent gate, special file) pins the tab on "Loading..." forever. There is no timeout anywhere in the chain, and clicking the file again does not retry: the tab is found by path and merely re-activated. Recovery requires closing the tab or restarting the app. Each stuck read also occupies a blocking slot in the async runtime, so several stuck tabs (e.g. restored at startup from a dead mount) can stall other IPC.

Reproduction (release build of f485396, macOS)

  1. Create a file whose read blocks indefinitely. Deterministic stand-in for the cloud-placeholder case: mkfifo workspace/research/stuck-doc.md.
  2. Open it in the app (Open With / file association).
  3. The tab shows "Loading..." indefinitely (screenshot taken 10 s after open; still identical after 10+ minutes). Clicking the file again does nothing.

Root cause

  • loading cleared only when the read settles: src/hooks/useTabs.ts:105-125; no timeout, no cancellation.
  • readTextFile is a single invoke (@tauri-apps/plugin-fs dist-js/index.js, readTextFile), and the plugin does a blocking file_handle.read_to_end inside the async command (tauri-plugin-fs-2.5.1/src/commands.rs:556-591), so a blocking syscall pends the promise forever and holds a runtime thread.
  • No retry on reopen: openInActive returns early via setActiveId when a tab with that path exists (src/hooks/useTabs.ts:139-143).
  • Same pattern for the workspace scan: scan_markdown is spawn_blocking with no timeout (src-tauri/src/tauri_api/mod.rs:28-34), so a hung filesystem leaves the sidebar scanning forever.

Proposed fix

  • Add a timeout to the tab load (and surface a retriable error state in the tab instead of an eternal spinner).
  • Make activating an existing tab retry the load when the previous load errored or is still pending past the timeout.
  • Consider a timeout or cancellation for the scan command, and non-blocking reads (or a bounded thread pool) on the Rust side.

Screenshot

Tab pinned on "Loading..." (unchanged after 10+ minutes; file exists, its read blocks):

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions