Skip to content

Bug: 0-byte lock file causes permanent cache lock (usage never refreshes) #202

@brandonwie

Description

@brandonwie

Summary

A 0-byte .usage-cache.lock file causes tryAcquireCacheLock() to return 'busy' permanently, preventing usage data from ever refreshing. The HUD falls back to stale cache data indefinitely.

Steps to Reproduce

  1. Run claude-hud normally (usage displays correctly)
  2. Simulate a crashed process that creates a 0-byte lock file:
    touch ~/.claude/plugins/claude-hud/.usage-cache.lock
  3. Wait for the cache TTL to expire (60s)
  4. Observe that usage data never refreshes — the HUD returns stale cache forever

Expected Behavior

The lock file should be treated as stale and removed, allowing a fresh API fetch. A lock file with no parseable timestamp is unrecoverable and should not block other processes.

Actual Behavior

readLockTimestamp() returns null for a 0-byte file. The stale-lock check on line 187 of usage-api.ts requires lockTimestamp != null before checking age, so the null case is never cleaned up:

// usage-api.ts:187
if (lockTimestamp != null && Date.now() - lockTimestamp > CACHE_LOCK_STALE_MS) {

Since null != null is false, the function falls through to return 'busy' on line 196. The lock persists until manually deleted.

How the 0-byte file is created

If the process crashes between fs.openSync(lockPath, 'wx') (line 171) and fs.writeFileSync(fd, String(Date.now())) (line 173), the lock file is created but never written to. The finally block closes the fd but doesn't clean up on failure.

Suggested Fix

Treat null timestamp as stale (unparseable = unrecoverable):

// Before (buggy):
if (lockTimestamp != null && Date.now() - lockTimestamp > CACHE_LOCK_STALE_MS) {

// After (fixed):
if (lockTimestamp === null || Date.now() - lockTimestamp > CACHE_LOCK_STALE_MS) {

This makes any unparseable lock file (0 bytes, corrupt data, NaN) get cleaned up immediately, matching the intent of the stale-lock mechanism.

Environment

  • OS: macOS 15.5 (Darwin 25.3.0)
  • Bun version: 1.3.10
  • Claude Code version: 2.1.74
  • claude-hud version: 0.0.9

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions