plandex-ai/plandex · error

failed to commit: %v

Error message

failed to commit: %v

What it means

Thrown in storeOnFinished (tell_stream_store.go:203) when repo.GitAddAndCommit fails to stage and commit the changes the model wrote to the working tree on the plan's branch. At this point the assistant message, description, and subtasks have already been persisted, so only the git commit of file changes failed. The wrapped git error is passed to onError and returned, causing the stream to end with a 500 'Error storing on finished'.

Source

Thrown at app/server/model/plan/tell_stream_store.go:203

		// store subtasks
		err = db.StorePlanSubtasks(currentOrgId, planId, state.subtasks)
		if err != nil {
			log.Printf("Error storing plan subtasks: %v\n", err)
			state.onError(onErrorParams{
				streamErr:      fmt.Errorf("failed to store plan subtasks: %v", err),
				storeDesc:      false,
				convoMessageId: assistantMsg.Id,
				commitMsg:      convoCommitMsg,
			})
			return err
		}

		log.Println("Comitting after store on finished")

		err = repo.GitAddAndCommit(branch, convoCommitMsg)
		if err != nil {
			state.onError(onErrorParams{
				streamErr:      fmt.Errorf("failed to commit: %v", err),
				storeDesc:      false,
				convoMessageId: assistantMsg.Id,
				commitMsg:      convoCommitMsg,
			})
			return err
		}
		log.Println("Assistant reply, description, and subtasks committed")

		return nil
	})

	if err != nil {
		log.Printf("Error storing on finished: %v\n", err)
		go notify.NotifyErr(notify.SeverityError, fmt.Errorf("error storing on finished: %v", err))

		active.StreamDoneCh <- &shared.ApiError{
			Type:   shared.ApiErrorTypeOther,
			Status: http.StatusInternalServerError,

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the wrapped '%v' cause in logs; if it mentions index.lock, remove stale .git/index.lock and retry.
  2. Confirm the plan branch exists and is not mid-merge/rebase; resolve or abort the conflicted state (git merge --abort / git rebase --abort) and retry.
  3. Ensure git user.name and user.email are set in the server environment.
  4. Verify the project path is a valid git repo with correct permissions for the server process.
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(filepath.Join(repoPath, ".git")); err != nil {
    return fmt.Errorf("not a git repository: %w", err)
}
if _, err := os.Stat(filepath.Join(repoPath, ".git", "index.lock")); err == nil {
    return fmt.Errorf("git index locked; another git operation may be in progress")
}
if out, err := exec.Command("git", "-C", repoPath, "config", "user.email"); err != nil || strings.TrimSpace(out.String()) == "" {
    return fmt.Errorf("git user.email not configured")
}

Try / catch

if err := repo.GitAddAndCommit(branch, msg); err != nil {
    if strings.Contains(err.Error(), "index.lock") {
        os.Remove(filepath.Join(repoPath, ".git", "index.lock"))
        return repo.GitAddAndCommit(branch, msg) // single retry
    }
    return fmt.Errorf("failed to commit: %w", err)
}

Prevention

When it happens

Trigger: repo.GitAddAndCommit(branch, convoCommitMsg) returns an error — typically because the repo working tree has unresolvable conflicts, git is locked (index.lock), no user.name/user.email is configured, the branch is in a detached/conflicted state, or the repo path is missing or not a git repository.

Common situations: Another process (IDE, user shell) holds index.lock; repo left mid-merge/rebase from a previous failed run; bare or non-git project dir passed to plandex; git identity not configured in the server's environment/container; filesystem permission problems on .git.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/c14d95fc6a98c117. Report an issue: GitHub.