{"record":{"id":"8d66a111edae9f88","repo":"plandex-ai/plandex","slug":"error-setting-git-config-s-to-s-for-dir-s-err","errorCode":null,"errorMessage":"error setting git config %s to %s for dir: %s, err: %v, output: %s","messagePattern":"error setting git config (.+?) to (.+?) for dir: (.+?), err: (.+?), output: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/git.go","lineNumber":650,"sourceCode":"\terrs := []error{}\n\tfor i := 0; i < len(paths); i++ {\n\t\terr := <-errCh\n\t\tif err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif len(errs) > 0 {\n\t\treturn fmt.Errorf(\"error removing lock files: %v\", errs)\n\t}\n\n\treturn nil\n}\n\nfunc setGitConfig(repoDir, key, value string) error {\n\tres, err := exec.Command(\"git\", \"-C\", repoDir, \"config\", key, value).CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error setting git config %s to %s for dir: %s, err: %v, output: %s\", key, value, repoDir, err, string(res))\n\t}\n\treturn nil\n}\n\nfunc gitWriteOperation(operation func() error, repoDir, label string) error {\n\tlog.Printf(\"[Git] gitWriteOperation - label: %s\", label)\n\tvar err error\n\tfor attempt := 0; attempt < maxGitRetries; attempt++ {\n\t\tif attempt > 0 {\n\t\t\tdelay := time.Duration(1<<uint(attempt-1)) * baseGitRetryDelay // Exponential backoff\n\t\t\ttime.Sleep(delay)\n\t\t\tlog.Printf(\"Retry attempt %d for git operation %s (delay: %v)\\n\", attempt+1, label, delay)\n\t\t}\n\n\t\terr = operation()\n\t\tif err == nil {\n\t\t\treturn nil\n\t\t}","sourceCodeStart":632,"sourceCodeEnd":668,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/git.go#L632-L668","documentation":"setGitConfig runs `git -C <repoDir> config <key> <value>` and wraps any failure — non-zero exit or inability to execute git — into this error including the key, value, repo dir, and git's combined stdout/stderr output. It is called from initGitRepo, so repo initialization fails if git cannot write the config (typically user.name/user.email or similar settings).","triggerScenarios":"initGitRepo invokes setGitConfig when: the repoDir does not exist or is not a git repository (git exits with 'not in a git directory' style errors); the .git/config file is not writable (EACCES); the git binary is missing from PATH; the config key/value is malformed (e.g. empty key or invalid section syntax).","commonSituations":"Docker/container images without git installed; running the app as a non-root user in a repo initialized by root; passing an invalid config key with a bad section delimiter; repo directory deleted or moved between init steps; disk full preventing config write.","solutions":["Read the `output` field in the error — git's own stderr names the exact cause (missing repo, bad key, permission denied).","Verify the git binary is installed and on PATH: `which git`; install git if missing.","Confirm repoDir exists and was successfully `git init`-ed before setGitConfig runs; check .git/config is writable by the app user.","Validate the key/value: keys need a valid `section.subsection.name` form and must not be empty; escape appropriately.","Check disk space (df -h) if git reports a write failure."],"exampleFix":"// before\nerr := setGitConfig(repoDir, key, value) // fails: fatal: not in a git directory\n// after: ensure repo exists and git is available first\nif _, err := os.Stat(filepath.Join(repoDir, \".git\")); os.IsNotExist(err) {\n    if out, err := exec.Command(\"git\", \"init\", repoDir).CombinedOutput(); err != nil {\n        return fmt.Errorf(\"git init failed: %v: %s\", err, out)\n    }\n}\nif err := setGitConfig(repoDir, key, value); err != nil { ... }","handlingStrategy":"validation","validationCode":"if _, err := exec.LookPath(\"git\"); err != nil {\n    return fmt.Errorf(\"git binary not found in PATH: %w\", err)\n}\nif fi, err := os.Stat(filepath.Join(repoDir, \".git\", \"config\")); err != nil || fi.IsDir() {\n    return fmt.Errorf(\"%s is not an initialized git repo\", repoDir)\n}","typeGuard":"func isGitConfigErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"error setting git config\")\n}","tryCatchPattern":"if err := initGitRepo(repoDir); err != nil {\n    if isGitConfigErr(err) && strings.Contains(err.Error(), \"executable file not found\") {\n        return fmt.Errorf(\"install git (apt-get install git) and retry\")\n    }\n    if isGitConfigErr(err) && strings.Contains(err.Error(), \"not in a git directory\") {\n        if out, ierr := exec.Command(\"git\", \"init\", repoDir).CombinedOutput(); ierr != nil {\n            return fmt.Errorf(\"git init failed: %v: %s\", ierr, out)\n        }\n        return initGitRepo(repoDir)\n    }\n    return err\n}","preventionTips":["Install git in every deployment image (Dockerfile: apt-get install -y git) and verify at startup with exec.LookPath.","Always run `git init` (and confirm .git/config exists) before setGitConfig.","Validate config keys match section.key syntax before passing to git.","Run the service as a user with write access to the repo directory."],"tags":["go","git","exec","configuration","environment"],"backgroundTag":"git-command-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}