{"record":{"id":"1aada71b20e283eb","repo":"anomalyco/sst","slug":"context-cancelled-while-waiting-for-dependency-ins","errorCode":null,"errorMessage":"context cancelled while waiting for dependency install lock","messagePattern":"context cancelled while waiting for dependency install lock","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/runtime/python/build.go","lineNumber":842,"sourceCode":"\t\tglobalDependencyInstallLocksMutex.Lock()\n\t\tcacheLock, exists := globalDependencyInstallLocks[cacheKey]\n\t\tif !exists {\n\t\t\tcacheLock = &sync.Mutex{}\n\t\t\tglobalDependencyInstallLocks[cacheKey] = cacheLock\n\t\t}\n\t\tglobalDependencyInstallLocksMutex.Unlock()\n\n\t\t// Acquire lock with timeout (5 minutes)\n\t\tlockAcquired := make(chan struct{})\n\t\tgo func() {\n\t\t\tcacheLock.Lock()\n\t\t\tclose(lockAcquired)\n\t\t}()\n\t\tselect {\n\t\tcase <-lockAcquired:\n\t\t\t// got the lock\n\t\tcase <-ctx.Done():\n\t\t\treturn fmt.Errorf(\"context cancelled while waiting for dependency install lock\")\n\t\tcase <-time.After(5 * time.Minute):\n\t\t\treturn fmt.Errorf(\"timed out waiting for dependency install lock after 5 minutes\")\n\t\t}\n\t\tdefer cacheLock.Unlock()\n\n\t\t// Check disk cache\n\t\tif entries, err := os.ReadDir(depsCacheDir); err == nil && len(entries) > 0 {\n\t\t\tif err := copyDependencyPackages(depsCacheDir, input.Out()); err != nil {\n\t\t\t\tslog.Warn(\"failed to copy from disk cache, will reinstall\", \"error\", err)\n\t\t\t\t// Remove bad cache and continue to reinstall\n\t\t\t\tos.RemoveAll(depsCacheDir)\n\t\t\t} else {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\n\t\t// Cache miss - create the cache directory\n\t\tif err := os.MkdirAll(depsCacheDir, 0755); err != nil {","sourceCodeStart":824,"sourceCodeEnd":860,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/runtime/python/build.go#L824-L860","documentation":"SST serializes dependency installs per cache key (requirements hash + architecture) with an in-process mutex so concurrent function builds don't race on the shared .deps disk cache. While blocked waiting for that lock, if the build context is cancelled (Ctrl-C, deploy timeout, parent context closed), this error is returned instead of hanging.","triggerScenarios":"ctx.Done() fires while another goroutine/build holds cacheLock in copySyncedDependencies — e.g. `sst deploy` cancelled mid-build while another `sst deploy`/`sst dev` builds the same project concurrently.","commonSituations":"User hits Ctrl-C during a long install; CI job killed by timeout while a parallel job holds the lock; `sst dev` restart triggered while deploy is installing deps.","solutions":["Simply rerun the deploy — the error is a cancellation, not corruption.","Avoid running multiple concurrent deploys of the same project (they contend on the same lock and .deps cache).","If CI timeouts cause it, raise the job timeout so the install can finish.","If a process was force-killed while holding the lock, restart the CLI process (locks are in-process, so a new run is clean)."],"exampleFix":"// before\n# terminal 1: sst deploy (installing...)\n# terminal 2: sst deploy  -> Ctrl-C / cancel -> context cancelled while waiting for dependency install lock\n// after\n$ sst deploy  # run one deploy at a time, or wait for the first to finish","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  await deploy();\n} catch (e) {\n  if (/context cancelled while waiting for dependency install lock/.test(e.message)) {\n    // expected on Ctrl-C / cancel; just wait for the other build then retry\n    await waitForOtherBuildToFinish();\n    await deploy();\n  } else throw e;\n}","preventionTips":["Run only one deploy of a given project at a time","Increase CI job timeouts so installs finish before cancellation","Avoid Ctrl-C mid-install; let the deploy complete or cancel cleanly before starting another","Restart sst dev only after deploys finish"],"tags":["concurrency","python","dependencies","cancellation"],"backgroundTag":"context-cancelled","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}