{"record":{"id":"1407d1830f32912d","repo":"gastownhall/beads","slug":"git-add-timed-out-after-s","errorCode":null,"errorMessage":"git add timed out after %s","messagePattern":"git add timed out after (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/export_auto.go","lineNumber":875,"sourceCode":"\tctx, cancel := context.WithTimeout(context.Background(), gitAddTimeout)\n\tdefer cancel()\n\t// Pass the basename only, defensively: cmd.Dir is the parent of path, so\n\t// a full path argument would double-root (cd .beads && git add\n\t// .beads/issues.jsonl → pathspec looks under .beads/.beads/) if a caller\n\t// ever passed a relative path here. Both current callers pass absolute\n\t// paths, so this guards against a regression rather than fixing a live\n\t// failure. See GH#4351.\n\t// Keep cmd.Dir = parent so GH#3311 hook worktree staging still resolves\n\t// the index path under the repo root (not bare \"issues.jsonl\" at root).\n\tcmd := exec.CommandContext(ctx, \"git\", \"add\", \"--\", filepath.Base(path))\n\tcmd.Dir = filepath.Dir(path)\n\tcmd.Env = env\n\t// Capture combined output so the caller's warning surfaces git's stderr\n\t// (e.g. \"paths are ignored\", \"Unable to create index.lock\") instead of\n\t// just the exit-status text.\n\tout, err := cmd.CombinedOutput()\n\tif ctx.Err() == context.DeadlineExceeded {\n\t\treturn fmt.Errorf(\"git add timed out after %s\", gitAddTimeout)\n\t}\n\tif err != nil {\n\t\tif trimmed := strings.TrimSpace(string(out)); trimmed != \"\" {\n\t\t\treturn fmt.Errorf(\"%w: %s\", err, trimmed)\n\t\t}\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc gitIndexLockPath(path string, env []string) (string, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), gitAddTimeout)\n\tdefer cancel()\n\tcmd := exec.CommandContext(ctx, \"git\", \"rev-parse\", \"--git-dir\")\n\tcmd.Dir = filepath.Dir(path)\n\tcmd.Env = env\n\tout, err := cmd.CombinedOutput()\n\tif ctx.Err() == context.DeadlineExceeded {","sourceCodeStart":857,"sourceCodeEnd":893,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/export_auto.go#L857-L893","documentation":"gitAddFile runs `git add` with a context timeout (gitAddTimeout). If the command does not finish before the deadline (context.DeadlineExceeded), this error is returned. It prevents auto-export from hanging indefinitely on a stuck git process.","triggerScenarios":"`git add <file>` launched by gitAddFile during auto-export exceeds gitAddTimeout — slow/remote filesystems, a git hook in pre-add, or a blocked index.lock causing git to wait.","commonSituations":"Large repos on NFS/network drives; another process holding index.lock so git add waits; antivirus or IDE hooks slowing git; heavily loaded CI runners.","solutions":["Clear the contention (remove stale index.lock if no git process is running) and let the next auto-export retry","Check for slow filesystems or hung git processes (ps aux | git) and kill/fix them","Increase gitAddTimeout if your environment legitimately needs longer, or skip auto-stage and run `bd sync`/`git add` manually"],"exampleFix":"// before\n// git add timed out after 10s\n// after\nrm -f .git/index.lock   # if stale\ngit add .beads/issues.jsonl && git commit -m \"sync beads\"","handlingStrategy":"retry","validationCode":"// Detect likely contention before triggering auto-export\nif lockExists, _ := exists(filepath.Join(\".git\", \"index.lock\")); lockExists {\n    return errors.New(\"git busy: index.lock present, skipping auto-export\")\n}","typeGuard":null,"tryCatchPattern":"err := doExport()\nif err != nil && strings.Contains(err.Error(), \"git add timed out\") {\n    // Backoff and retry once\n    time.Sleep(5 * time.Second)\n    err = doExport()\n}","preventionTips":["Keep repos on local SSDs where possible; avoid NFS for .git","Raise gitAddTimeout in slow/CI environments","Investigate hung git processes if timeouts recur","Exclude repo directories from real-time antivirus scanning"],"tags":["git","timeout","auto-export"],"backgroundTag":"git-add-timeout","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}