plandex-ai/plandex · error

%v (from err.Error())

Error message

%v (from err.Error())

What it means

onBuildFileError is the generic per-file build error handler: whenever a file build (execPlanBuild, buildFile, buildStructuredEdits, buildWholeFileFallback) fails for any reason, the raw err.Error() text is sent to the client as a 500 ApiError via StreamDoneCh and recorded on build.Error via db.SetBuildError. The message shown is the underlying error, so its content varies — LLM stream failures, parse failures, context cancellation, etc.

Source

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

	activePlan := GetActivePlan(planId, branch)

	if activePlan == nil {
		log.Println("onBuildFileError - Active plan not found")
		return
	}

	log.Printf("Error for file %s: %v\n", filePath, err)

	activeBuild.Success = false
	activeBuild.Error = err

	go notify.NotifyErr(notify.SeverityError, fmt.Errorf("error for file %s: %v", filePath, err))

	activePlan.StreamDoneCh <- &shared.ApiError{
		Type:   shared.ApiErrorTypeOther,
		Status: http.StatusInternalServerError,
		Msg:    err.Error(),
	}

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

	build.Error = err.Error()

	err = db.SetBuildError(build)
	if err != nil {
		log.Printf("Error setting build error: %v\n", err)
	}
}

func (fileState *activeBuildStreamFileState) buildNextInQueue() bool {
	filePath := fileState.filePath
	activePlan := GetActivePlan(fileState.plan.Id, fileState.branch)
	if activePlan == nil {
		log.Println("onFinishBuildFile - Active plan not found")

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the actual Msg sent to the client (it's err.Error()) and the server log line "Error for file <path>: ..." to identify the underlying failure
  2. If it's a provider/stream error, check API keys, rate limits, and provider status, then retry the build
  3. If the response failed to parse/apply, retry the operation or switch to a stronger model / whole-file fallback
  4. If context length is implicated, add fewer files to context or reduce the target file size
  5. The build's Error field is persisted via db.SetBuildError — inspect the build record for the retained message
Defensive patterns

Strategy: try-catch

Try / catch

// the client receives the 500 ApiError on the stream; handle and inspect Msg
resp, err := client.GetPlanBuildStream(...)
if apiErr, ok := err.(*shared.ApiError); ok {
	log.Printf("build failed for plan: %s (type=%s status=%d)", apiErr.Msg, apiErr.Type, apiErr.Status)
	if strings.Contains(apiErr.Msg, "context length") {
		// trim plan context and retry
	} else if isProviderError(apiErr.Msg) {
		// check keys/rate limits and retry
	}
}

Prevention

When it happens

Trigger: Any failure inside a file build path that calls onBuildFileError: the model stream errored or was canceled, the LLM response failed validation/parsing into file edits, context length exceeded, or an internal step returned an error that bubbles to this handler.

Common situations: LLM provider outages or rate limits during a build; malformed model output that can't be applied as edits; plan canceled while a file was streaming; context window too small for the target file; misconfigured API keys causing provider errors.

Related errors


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