From e802d0681e155ace7af9651e21741a47aec67f0c Mon Sep 17 00:00:00 2001 From: Ash Brener Date: Wed, 28 Jan 2026 13:08:32 +0200 Subject: [PATCH] workspace-sync: clear stale rclone locks on startup --- src/gateway/workspace-sync-manager.ts | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/gateway/workspace-sync-manager.ts b/src/gateway/workspace-sync-manager.ts index 3482e13ef..99f637f7b 100644 --- a/src/gateway/workspace-sync-manager.ts +++ b/src/gateway/workspace-sync-manager.ts @@ -5,6 +5,9 @@ * This is a pure file operation that incurs zero token cost. */ +import { existsSync, readdirSync, unlinkSync } from "node:fs"; +import { join } from "node:path"; +import { homedir } from "node:os"; import type { MoltbotConfig } from "../config/config.js"; import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js"; import { @@ -129,6 +132,31 @@ async function runSync(): Promise { } } +/** + * Clear stale rclone bisync lock files. + * Called on startup since a restart means any prior sync was interrupted. + */ +function clearStaleLocks(logger: SyncManagerLogger): void { + const lockDir = join(homedir(), ".cache", "rclone", "bisync"); + try { + if (!existsSync(lockDir)) return; + + const files = readdirSync(lockDir); + const lockFiles = files.filter((f) => f.endsWith(".lck")); + + for (const lockFile of lockFiles) { + try { + unlinkSync(join(lockDir, lockFile)); + logger.info(`[workspace-sync] Cleared stale lock: ${lockFile}`); + } catch { + // Ignore errors deleting individual files + } + } + } catch { + // Lock dir doesn't exist or can't be read - that's fine + } +} + /** * Start the background sync manager. * Called when the gateway starts. @@ -146,6 +174,9 @@ export function startWorkspaceSyncManager(cfg: MoltbotConfig, logger: SyncManage return; } + // Clear any stale locks from prior interrupted syncs + clearStaleLocks(logger); + const intervalSeconds = syncConfig.interval ?? 0; if (intervalSeconds <= 0) { logger.info("[workspace-sync] Periodic sync disabled (interval=0)");