santifer/career-ops · critical · Error

Cannot verify tracker lock ownership at ${lockDir}

Error message

Cannot verify tracker lock ownership at ${lockDir}

What it means

During tracker lock release (the ownerVerified branch), the code re-reads owner.json to confirm the releasing caller still owns the lock. If readLockOwner returns null/undefined (cannot parse owner.json) BUT the file exists on disk, it throws an Error — because it cannot prove ownership either way (the file is present but unreadable/corrupt). This is a fail-safe against releasing a lock the caller may not own.

Source

Thrown at tracker-utils.mjs:385

              currentDir = statSync(lockDir);
            } catch (err) {
              if (err?.code === 'ENOENT') {
                released = true;
                return;
              }
              throw err;
            }
            if (!sameLockDirectory(verifiedDir, currentDir)) {
              released = true;
              return;
            }
            const owner = readLockOwner(lockDir);
            if (owner && owner.token !== token) {
              released = true;
              return;
            }
            if (!owner && existsSync(join(lockDir, 'owner.json'))) {
              throw new Error(`Cannot verify tracker lock ownership at ${lockDir}`);
            }
          } else {
            let beforeRead;
            try {
              beforeRead = statSync(lockDir);
            } catch (err) {
              if (err?.code === 'ENOENT') {
                released = true;
                return;
              }
              throw err;
            }
            const owner = readLockOwner(lockDir);
            if (owner?.token !== token) {
              if (owner) released = true;
              else throw new Error(`Cannot verify tracker lock ownership at ${lockDir}`);
              return;
            }

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Remove the stale lock directory manually (locate the .lock dir near the tracker, delete it) — it will be recreated on next acquire.
  2. Use the force release path if available in the calling code to bypass ownership checks administratively.
  3. Investigate what corrupted owner.json (concurrent writers, crash) to prevent recurrence.
  4. Increase CAREER_OPS_TRACKER_LOCK_STALE_MS if long-held locks are being scavenged mid-operation.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await operation();
} catch (err) {
  if (err.message.includes('Cannot verify tracker lock ownership')) {
    console.error('Stale/corrupt lock detected. Removing lock dir and retrying.');
    fs.rmSync(lockDir, { recursive: true, force: true });
    await operation();
  } else throw err;
}

Prevention

When it happens

Trigger: owner.json exists but is corrupt/truncated (invalid JSON), or readLockOwner encounters a permission error reading it, during the release() call on a verified lock. This is a TOCTOU edge: the file was readable at acquire time but became corrupt before release.

Common situations: Concurrent processes interfering with the lock directory; a crash mid-write leaving a partial owner.json; filesystem issues; manual tampering with the lock directory's owner.json between acquire and release.

Related errors


AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13). Data as JSON: /api/errors/0822c61595da4f9d. Report an issue: GitHub.