paperclipai/paperclip · error

Timed out waiting for workspace restore lock at

Error message

Timed out waiting for workspace restore lock at ${lockDir}

What it means

Error "Timed out waiting for workspace restore lock at ${lockDir}" thrown in paperclipai/paperclip.

Solutions

  1. Remove the stale workspace restore lock at ${lockDir} if no process holds it, then retry.
  2. Wait for the concurrent restore to finish and retry.

When it happens

Trigger: Thrown at packages/adapter-utils/src/workspace-restore-merge.ts:154 when the library encounters an invalid state.

Common situations: See trigger scenarios.

Understand the failure class


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-08-18). Data as JSON: /api/errors/c4f9db16e87f5df9. Report an issue: GitHub.

Appendix: source

Thrown at packages/adapter-utils/src/workspace-restore-merge.ts:235

  | { readonly ok: true }
  | { readonly ok: false; readonly code: WorkspaceRestoreFailureCode };

/**
 * Classifies a caught workspace-restore error into one allowlisted code. Maps
 * `EACCES` and `EPERM` to a permission failure, the merge-lock timeout
 * (matched by {@link WORKSPACE_RESTORE_LOCK_TIMEOUT_CODE}, never by the error
 * message text) to a lock-timeout failure, and every other error to a generic
 * failure. Never reads or returns `Error.message`, a filesystem path, or a
 * process id.
 */
export function classifyWorkspaceRestoreFailure(error: unknown): WorkspaceRestoreFailureCode {
  const code = error && typeof error === "object" ? (error as NodeJS.ErrnoException).code : undefined;
  if (code === "EACCES" || code === "EPERM") return "restore_permission_denied";
  if (code === WORKSPACE_RESTORE_LOCK_TIMEOUT_CODE) return "restore_lock_timeout";
  return "restore_failed";
}

/**
 * The fixed, allowlisted line an ACP adapter writes to the run log when a
 * workspace restore fails. Every call site must pass this to `onLog` instead
 * of the caught error's own message: the caught error can carry a host
 * filesystem path or the lock owner's process id, and the run log is
 * readable by any same-company actor. Never add the code's raw
 * `Error.message` to this text.
 */
export function describeWorkspaceRestoreFailure(code: WorkspaceRestoreFailureCode): string {
  switch (code) {
    case "restore_permission_denied":
      return "the restore could not write to the workspace (permission denied)";
    case "restore_lock_timeout":
      return "the restore timed out waiting for the workspace merge lock";
    case "restore_failed":
      return "the restore failed";
  }
}

View on GitHub (pinned to 01ad858492)