plandex-ai/plandex · error

Error storing plan build result: %v

Error message

Error storing plan build result: %v

What it means

After storing the per-file plan result inside a repo write lock (db.StorePlanResult) or acquiring the lock itself via db.ExecRepoOperation, any error is wrapped/logged as "Error storing plan build result: %v" and pushed to StreamDoneCh as a 500 ApiError. It indicates the persistence step of the file build failed — either the repo lock couldn't be acquired (canceled, timed out, deadlocked) or the database write for the PlanFileResult failed.

Source

Thrown at app/server/model/plan/build_finish.go:222

		Reason:      "store plan result",
	}, func(repo *db.GitRepo) error {
		log.Println("Storing plan result", planRes.Path)

		err := db.StorePlanResult(planRes)
		if err != nil {
			log.Printf("Error storing plan result: %v\n", err)
			return err
		}

		return nil
	})

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

		activePlan.StreamDoneCh <- &shared.ApiError{
			Type:   shared.ApiErrorTypeOther,
			Status: http.StatusInternalServerError,
			Msg:    "Error storing plan build result: " + err.Error(),
		}
		return
	}

	fileState.builderRun.FinishedAt = time.Now()
	hooks.ExecHook(hooks.DidFinishBuilderRun, hooks.HookParams{
		Auth:                      fileState.auth,
		Plan:                      fileState.plan,
		DidFinishBuilderRunParams: &fileState.builderRun,
	})

	log.Printf("Finished building file %s - setting activeBuild.Success to true\n", filePath)
	// log.Println(spew.Sdump(activeBuild))

	fileState.onBuildProcessed(activeBuild)
}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the full wrapped error in the server log to distinguish a lock-acquisition failure from a StorePlanResult DB error
  2. Verify the database is reachable and healthy (connection pool, disk space, migrations)
  3. Retry the plan build if the failure was transient (DB restart, lock contention)
  4. Check for leaked repo locks from crashed builds and ensure ExecRepoOperation releases locks (look for stale lock rows/locks for the plan branch)
  5. Avoid canceling plans mid-build when possible; cancelations can leave operations racing for locks
Defensive patterns

Strategy: retry

Validate before calling

// before starting builds, verify DB reachability
if err := db.Ping(); err != nil {
	return fmt.Errorf("database unreachable before plan build: %v", err)
}

Try / catch

err := db.ExecRepoOperation(params, func(repo *db.GitRepo) error {
	return db.StorePlanResult(planRes)
})
if err != nil {
	switch {
	case errors.Is(err, context.Canceled):
		// user canceled; don't retry
	case isLockTimeout(err):
		// retry with backoff
	default:
		// DB error: check database health, then retry or alert
	}
}

Prevention

When it happens

Trigger: db.ExecRepoOperation fails to get the write lock (another build holds it, plan context canceled, lock timeout) or db.StorePlanResult returns a database error (connection refused, constraint violation, disk full) for planRes.Path.

Common situations: Postgres down or restarting during a build; concurrent builds on the same plan/branch contending for the repo write lock; plan canceled by the user mid-build so the context is canceled; disk exhaustion on the database volume.

Related errors


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