{"record":{"id":"cdd888c605a1807c","repo":"gohugoio/hugo","slug":"failed-to-acquire-a-build-lock-w","errorCode":null,"errorMessage":"failed to acquire a build lock: %w","messagePattern":"failed to acquire a build lock: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hugolib/hugo_sites_build.go","lineNumber":97,"sourceCode":"\t}\n\n\tinfol := h.Log.InfoCommand(\"build\")\n\tdefer loggers.TimeTrackf(infol, time.Now(), nil, \"\")\n\tdefer func() {\n\t\th.reportProgress(func() (state terminal.ProgressState, progress float64) {\n\t\t\treturn terminal.ProgressHidden, 1.0\n\t\t})\n\t\th.BuildState.BuildCounter.Add(1)\n\t}()\n\n\tif h.Deps == nil {\n\t\tpanic(\"must have deps\")\n\t}\n\n\tif !config.NoBuildLock {\n\t\tunlock, err := h.BaseFs.LockBuild()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to acquire a build lock: %w\", err)\n\t\t}\n\t\tdefer unlock()\n\t}\n\n\tdefer func() {\n\t\tfor _, s := range h.Sites {\n\t\t\ts.Deps.BuildEndListeners.Notify()\n\t\t}\n\t}()\n\n\terrCollector := h.StartErrorCollector()\n\terrs := make(chan error)\n\n\tgo func(from, to chan error) {\n\t\tvar errors []error\n\t\ti := 0\n\t\tfor e := range from {\n\t\t\ti++","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/hugolib/hugo_sites_build.go#L79-L115","documentation":"Returned at the very start of a build when LockBuild() cannot acquire the build mutex. The %w is the lock-acquisition error from the buildMu (a file/OS-level lock guarding the working tree).","triggerScenarios":"Raised at hugo_sites_build.go:97 when h.BaseFs.LockBuild() fails (b.buildMu.Lock() errors). Occurs if the lock file backing buildMu cannot be created/acquired — e.g. resources dir not writable, or a stale/corrupt lock.","commonSituations":"Concurrent `hugo`/`hugo server`/`hugo mod` processes racing the same project; resources/ or working dir on a read-only filesystem; a previous crashed build left a stale lock; permissions changed in CI.","solutions":["Ensure no other Hugo process is running against the same project (check `ps` / `hugo --renderSegments` locks).","Make the resources/ and working directories writable (chmod/chown).","Remove a stale lock file under resources/_gen or the build lock path, then rebuild.","If running embedded, pass NoBuildLock=true only for non-overlapping single-process builds."],"exampleFix":"// before: two concurrent builds on same workdir\ngo func(){ _ = hugo.Build(cfg) }()\nhugo.Build(cfg)  // -> failed to acquire a build lock\n\n// after: serialize builds or disable the lock for single-process use\nhugo.Build(BuildCfg{NoBuildLock: true})","handlingStrategy":"validation","validationCode":"// Ensure the work dir + resources are writable and no other Hugo process holds the lock.\nif !writable(h.workingDir) { return errors.New(\"workdir not writable\") }\nif otherHugoRunning() { return errors.New(\"another hugo build is running\") }","typeGuard":null,"tryCatchPattern":"unlock, err := h.BaseFs.LockBuild()\nif err != nil {\n    if isLockHeld(err) { return fmt.Errorf(\"build in progress; retry later\") }\n    return fmt.Errorf(\"failed to acquire a build lock: %w\", err)\n}\ndefer unlock()","preventionTips":["Serialize Hugo builds per project; don't run server + CLI build concurrently.","Keep resources/ on a writable filesystem.","Clean stale locks after a crashed build before re-running."],"tags":["build","locking","concurrency","hugo"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}