{"record":{"id":"c828366d0bc820b5","repo":"anomalyco/sst","slug":"errlockexists","errorCode":"ErrLockExists","errorMessage":"Concurrent update detected, run `sst unlock --stage=<stage>` to delete lock file and retry.","messagePattern":"Concurrent update detected, run `sst unlock --stage=<stage>` to delete lock file and retry\\.","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/project/provider/provider.go","lineNumber":68,"sourceCode":"}\n\nfunc (dt *DevTransport) Publish(input interface{}) error {\n\tjsonBytes, err := json.Marshal(input)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdt.Out <- string(jsonBytes)\n\treturn nil\n}\n\ntype DevSession interface {\n\tCleanup() error\n\tPublish(json string) error\n}\n\nconst SSM_NAME_BOOTSTRAP = \"/sst/bootstrap\"\n\nvar ErrLockExists = fmt.Errorf(\"Concurrent update detected, run `sst unlock --stage=<stage>` to delete lock file and retry.\")\nvar ErrLockNotFound = fmt.Errorf(\"Lock not found\")\nvar passphraseCache = map[Home]map[string]string{}\n\nfunc Copy(from Home, to Home, app, stage string) error {\n\treader, err := from.getData(\"app\", app, stage)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = to.putData(\"app\", app, stage, reader)\n\tif err != nil {\n\t\treturn err\n\t}\n\treader, err = from.getData(\"secret\", app, stage)\n\tif err != nil {\n\t\treturn err\n\t}\n\tto.putData(\"secret\", app, stage, reader)\n\treturn nil","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/project/provider/provider.go#L50-L86","documentation":"`ErrLockExists` is returned by `Lock`/`Run` when the per-stage state lock file already exists, meaning another SST update appears to be in progress. SST serializes deployments per stage with a lock to prevent concurrent updates from corrupting state.","triggerScenarios":"Running two `sst deploy`/`sst dev` processes for the same stage simultaneously; a previous run crashed or lost network without releasing the lock (stale lock).","commonSituations":"CI pipeline overlapping a locally running deploy; Ctrl-C / laptop sleep during deploy leaving an orphaned lock; two teammates deploying the same stage.","solutions":["Ensure no other sst process is running against this stage, then run `sst unlock --stage=<stage>` and retry","If in CI, cancel the overlapping job before retrying","If locks recur from crashes, run the unlock command after each interrupted deploy"],"exampleFix":"$ sst unlock --stage=prod\n$ sst deploy --stage=prod","handlingStrategy":"try-catch","validationCode":"aws ssm get-parameter --name /sst/lock/<app>/<stage> 2>/dev/null && echo \"stage locked\" || echo \"stage free\"","typeGuard":null,"tryCatchPattern":"err := sstDeploy(ctx, stage)\nif errors.Is(err, sst.ErrLockExists) {\n    exec.Command(\"sst\", \"unlock\", \"--stage=\"+stage).Run()\n    err = sstDeploy(ctx, stage) // retry once\n}","preventionTips":["Never run two sst commands for the same stage concurrently","Add a CI concurrency group per stage in your pipeline","Run `sst unlock` after any interrupted deploy"],"tags":["state","lock","concurrency","deploy"],"backgroundTag":"concurrent-update-lock","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}