withScriptLock Helper

Standalone projects and library code don't get a Document Lock. When the critical section is the script project itself — watermark updates, Script Properties, a shared import cursor — wrap it with LockService.getScriptLock() and always unlock in finally.

What you'll need

  • A critical section that should serialize across all users / all installs of this project (or the standalone script)
  • Contrast with withDocumentLock (bound spreadsheet) and withUserLock (per-user only)

Why Script Lock

Lock Serializes
Document Everyone on this spreadsheet
User The same user's overlapping runs
Script Anyone running this project / library

Use Script Lock for standalone web apps, libraries, and property-store races that aren't tied to one bound file.

How to use this snippet

function withScriptLock(fn, waitMs) { waitMs = waitMs || 30000; var lock = LockService.getScriptLock(); if (!lock.tryLock(waitMs)) { throw new Error('Could not acquire script lock within ' + waitMs + 'ms'); } try { return fn(); } finally { lock.releaseLock(); } } function bumpImportCursor(nextValue) { return withScriptLock(function () { var props = PropertiesService.getScriptProperties(); var current = Number(props.getProperty('importCursor') || '0'); if (nextValue <= current) return current; // already advanced props.setProperty('importCursor', String(nextValue)); return nextValue; }); }

Tips:

  • Same try/finally discipline as the document/user helpers — a thrown error must still releaseLock.
  • Keep UrlFetch and other slow I/O outside the lock when you can; hold it only for the read-modify-write.
  • Fail loud when tryLock returns false — silent skips look like successful runs.

Happy Coding!

NitroGAS Chrome Extension

Want this snippet handy inside the Apps Script editor? NitroGAS gives you free themes and snippets — plus optional Co-Pilot when you want a boost (1-week, 1-month, or yearly passes — no subscription). Happy Coding!

Get the Extension