plandex-ai/plandex · error

error starting whole file build: %v

Error message

error starting whole file build: %v

What it means

In buildRace, startWholeFileBuild launches a goroutine that runs the whole-file fallback build; its recover() defer catches any panic in that goroutine, logs the stack, converts the panic value to "error starting whole file build: %v" and forwards it via sendErr to errCh before runtime.Goexit() stops the goroutine. This error means the fallback whole-file build path crashed unexpectedly (not that the model output was invalid).

Source

Thrown at app/server/model/plan/build_race.go:86

	}

	sendErr := func(err error) {
		select {
		case errCh <- err:
		case <-buildCtx.Done():
			log.Printf("buildRace - context canceled, skipping sendErr")
		}
	}

	startedFallbacks := false

	startWholeFileBuild := func(comments string) {
		log.Printf("buildRace - starting whole file fallback build")
		go func() {
			defer func() {
				if r := recover(); r != nil {
					log.Printf("panic in startWholeFileBuild: %v\n%s", r, debug.Stack())
					sendErr(fmt.Errorf("error starting whole file build: %v", r))
					runtime.Goexit() // don't allow outer function to continue and double-send to channel
				}
			}()
			select {
			case <-buildCtx.Done():
				log.Printf("buildRace - context already canceled, skipping whole file build")
				return
			default:
			}

			content, err := fileState.buildWholeFileFallback(buildCtx, proposedContent, desc, comments, sessionId)

			if err != nil {
				if errors.Is(err, context.Canceled) {
					log.Printf("Context canceled during whole file build")
					return
				}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Inspect the panic stack trace logged as "panic in startWholeFileBuild" for the exact crash site
  2. Validate fileState.preBuildState and proposedContent are non-nil before calling startWholeFileBuild
  3. Check buildCtx is still live (the goroutine already skips when canceled) and sessionId state is valid
  4. Add guards/fixes in buildWholeFileFallback, then re-run the build; sendErr safely feeds the race's errCh

Example fix

// before
startWholeFileBuild(comments) // panics when proposedContent is nil
// after
if proposedContent == "" || fileState.preBuildState == nil {
	sendErr(fmt.Errorf("cannot start whole file build: missing file state or proposed content"))
	return
}
startWholeFileBuild(comments)
Defensive patterns

Strategy: validation

Validate before calling

if fileState == nil || fileState.preBuildState == nil || proposedContent == "" {
	return fmt.Errorf("cannot run whole file fallback: missing file state or proposed content")
}
if err := buildCtx.Err(); err != nil {
	return fmt.Errorf("build context already canceled: %w", err)
}

Type guard

func canRunWholeFileFallback(fs *activeBuildStreamFileState, proposed string) bool {
	return fs != nil && fs.preBuildState != nil && proposed != ""
}

Try / catch

res, err := buildRace(buildCtx, cancelBuild, params)
if err != nil {
	if strings.Contains(err.Error(), "error starting whole file build") {
		// panic in fallback goroutine: inspect stack trace, don't blindly retry
		log.Printf("whole-file fallback crashed: %v", err)
	}
	return res, err
}

Prevention

When it happens

Trigger: A panic occurs in the goroutine started by startWholeFileBuild — before or inside fileState.buildWholeFileFallback(buildCtx, proposedContent, desc, comments, sessionId) — e.g. nil fileState fields (preBuildState), bad proposedContent assumptions, or a nil map write in fallback setup.

Common situations: proposedContent or file state is nil/malformed when the race detects syntax errors and starts the fallback; session/context state torn down while the fallback goroutine starts; a regression in buildWholeFileFallback or syntax parsing utilities.

Related errors


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