plandex-ai/plandex · error
Error storing plan result: planRes is nil
Error message
Error storing plan result: planRes is nil
What it means
onFinishBuildFile is the terminal callback for a single-file plan build and expects a non-nil *db.PlanFileResult holding the LLM's constructed file content. When it is called with planRes == nil, Plandex sends "Error storing plan result: planRes is nil" as a 500 ApiError on StreamDoneCh and reports via notify. This is an internal invariant violation: some code path invoked the finish callback without a produced result.
Source
Thrown at app/server/model/plan/build_finish.go:188
activeBuild := fileState.activeBuild
activePlan := GetActivePlan(planId, branch)
if activePlan == nil {
log.Println("onFinishBuildFile - Active plan not found")
return
}
filePath := fileState.filePath
log.Printf("onFinishBuildFile: %s\n", filePath)
if planRes == nil {
log.Println("onFinishBuildFile - planRes is nil")
go notify.NotifyErr(notify.SeverityError, fmt.Errorf("onFinishBuildFile: planRes is nil"))
activePlan.StreamDoneCh <- &shared.ApiError{
Type: shared.ApiErrorTypeOther,
Status: http.StatusInternalServerError,
Msg: "Error storing plan result: planRes is nil",
}
return
}
err := db.ExecRepoOperation(db.ExecRepoOperationParams{
OrgId: currentOrgId,
UserId: fileState.currentUserId,
PlanId: planId,
Branch: branch,
PlanBuildId: build.Id,
Scope: db.LockScopeWrite,
Ctx: activePlan.Ctx,
CancelFn: activePlan.CancelFn,
Reason: "store plan result",
}, func(repo *db.GitRepo) error {
log.Println("Storing plan result", planRes.Path)View on GitHub (pinned to e2d772072e)
Solutions
- Inspect server logs for the preceding "onFinishBuildFile - planRes is nil" line and the model stream outcome to find which caller produced the nil result
- Check whether the model response for that file was empty/truncated (API errors, token limits) and retry the plan operation
- Audit the calling path (buildFile / buildStructuredEdits) to ensure every branch constructs a *db.PlanFileResult before calling onFinishBuildFile
- Ensure the plan's configured model is returning valid file content (switch model or reduce file size if responses are cut off)
Example fix
// before
res, err := parsePlanFileResult(streamRes)
if err != nil {
return err
}
state.onFinishBuildFile(res)
// after
res, err := parsePlanFileResult(streamRes)
if err != nil {
return err
}
if res == nil {
return fmt.Errorf("no plan file result produced for %s", filePath)
}
state.onFinishBuildFile(res) Defensive patterns
Strategy: type-guard
Validate before calling
// guard before invoking the finish callback
if planRes == nil {
return fmt.Errorf("buildFile(%s): model stream ended without a file result", filePath)
} Type guard
func isValidPlanFileResult(res *db.PlanFileResult) bool {
return res != nil && res.Path != ""
}
// at the call site:
if !isValidPlanFileResult(planRes) {
// route to error handler instead of onFinishBuildFile
} Try / catch
// in Go there is no try/catch; guard the callback input
if planRes == nil {
fileState.onBuildFileError(fmt.Errorf("planRes is nil for %s", filePath))
return
} Prevention
- Never call onFinishBuildFile directly with a result that came from a parse function without a nil check
- Route all build failures through onBuildFileError instead of silently skipping result construction
- Add tests for empty/truncated model responses in buildFile and buildStructuredEdits
- Log model stream completion status before invoking finish callbacks
When it happens
Trigger: buildFile or buildStructuredEdits reaching onFinishBuildFile with a nil planRes — e.g. the model stream ended without yielding a file result, an upstream code path forgot to assign the result after parsing the response, or a fallback/error path calls the finish handler directly without constructing a PlanFileResult.
Common situations: Model API responses that come back truncated or empty so parsing produces no result; new/untested plan modes (e.g. structured edits) that return nil on certain operation shapes; custom forks where the streaming callback was modified; races where the stream was canceled before the result was captured.
Related errors
- %v (from err.Error())
- error committing plan build: %v
- Error storing plan build result: %v
- error getting plan modelContext: %v
- error getting pending builds by path: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/3445ac975da0df86.
Report an issue: GitHub.