plandex-ai/plandex · error

Error rejecting result:

Error message

Error rejecting result: 

What it means

The repository operation inside RejectFileHandler's ExecRepoOperation transaction failed — either db.RejectPlanFile (DB/repo update) or repo.GitAddAndCommit (git commit of the reverted file) returned an error. The handler maps any of these to HTTP 500.

Source

Thrown at app/server/handlers/plans_changes.go:355

		CancelFn:       cancel,
		ClearRepoOnErr: true,
	}, func(repo *db.GitRepo) error {
		err = db.RejectPlanFile(auth.OrgId, planId, req.FilePath, time.Now())
		if err != nil {
			return err
		}

		err = repo.GitAddAndCommit(branch, fmt.Sprintf("🚫 Rejected pending changes to file: %s", req.FilePath))
		if err != nil {
			return fmt.Errorf("error committing rejected changes: %v", err)
		}

		return nil
	})

	if err != nil {
		log.Printf("Error rejecting result: %v\n", err)
		http.Error(w, "Error rejecting result: "+err.Error(), http.StatusInternalServerError)
		return
	}

	log.Println("Successfully rejected plan file", req.FilePath)
}

func RejectFilesHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("Received request for RejectFilesHandler")

	auth := Authenticate(w, r, true)
	if auth == nil {
		return
	}

	vars := mux.Vars(r)
	planId := vars["planId"]
	branch := vars["branch"]

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the wrapped err.Error() in the 500 response to see whether the DB step or the git commit step failed
  2. If it's a git error, check for stale .git/index.lock in the plan's repo and retry (ClearRepoOnErr already reset it)
  3. Verify the plan/branch still exist and no other operation holds the write lock
  4. Retry the request; if DB errors persist, check database connectivity/logs

Example fix

// server already resets the repo on failure — client-side recovery
// before
await rejectFile(planId, branch, filePath);
// after
try {
  await rejectFile(planId, branch, filePath);
} catch (e) {
  if (e.status === 500) await retryWithBackoff(() => rejectFile(planId, branch, filePath));
}
Defensive patterns

Strategy: retry

Validate before calling

const plan = await getPlan(planId, branch);
if (!plan.pendingFiles?.includes(filePath)) throw new Error('File has no pending changes to reject');

Type guard

function isGitLockError(msg) { return typeof msg === 'string' && msg.includes('index.lock'); }

Try / catch

try { await rejectFile(planId, branch, filePath); } catch (e) { if (e.status === 500 && !isGitLockError(e.message)) await retryWithBackoff(() => rejectFile(planId, branch, filePath)); else throw e; }

Prevention

When it happens

Trigger: RejectPlanFile fails (plan/file row not found, DB error), or GitAddAndCommit fails (git lock file present, dirty/unmerged index, missing branch, repo corruption) while rejecting a single file's pending changes.

Common situations: Concurrent operations holding the repo write lock; leftover .git/index.lock after a crash; branch deleted while request in flight; DB connectivity loss mid-transaction; ClearRepoOnErr wipes the local repo so a retry starts clean.

Related errors


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