plandex-ai/plandex · error

error building race: %v

Error message

error building race: %v

What it means

buildStructuredEdits wraps any failure returned by fileState.buildRace (the fallback LLM race that fixes a failed auto-apply) into "error building race: %v" and forwards it via fileState.onBuildFileError. It is thrown when the race of fast-apply/model-based repair paths fails for a non-ApiError reason, meaning the file's edits could not be finalized. If the underlying error is a *shared.ApiError it is instead streamed to activePlan.StreamDoneCh and this message is not produced.

Source

Thrown at app/server/model/plan/build_structured_edits.go:171

			proposedContent: proposedContent,
			desc:            desc,
			reasons:         autoApplyRes.NeedsVerifyReasons,
			syntaxErrors:    autoApplySyntaxErrors,

			didCallFastApply: calledFastApply,
			fastApplyCh:      fastApplyCh,

			sessionId: activePlan.SessionId,
		}

		buildRaceResult, err := fileState.buildRace(buildCtx, cancelBuild, buildRaceParams)
		if err != nil {
			if apiErr, ok := err.(*shared.ApiError); ok {
				activePlan.StreamDoneCh <- apiErr
				return
			} else {
				log.Printf("buildStructuredEdits - %s - error building race: %v\n", filePath, err)
				fileState.onBuildFileError(fmt.Errorf("error building race: %v", err))
			}
			return
		}

		updated = buildRaceResult.content
	}

	// output diff and store build results
	buildInfo := &shared.BuildInfo{
		Path:      filePath,
		NumTokens: 0,
		Finished:  true,
	}
	log.Printf("streaming build info for finished file %s\n", filePath)
	activePlan.Stream(shared.StreamMessage{
		Type:      shared.StreamMessageBuildInfo,
		BuildInfo: buildInfo,
	})

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check the wrapped inner error in the log line to identify the root cause (network, auth, or model output).
  2. Verify LLM provider credentials and rate limits; if it's a transient network failure, retry the plan build.
  3. If the underlying error is actually an API error, ensure it is typed as *shared.ApiError so it routes through StreamDoneCh instead of this path.
  4. Increase build context timeout or reduce file size so the repair race can complete.

Example fix

// before
buildRaceResult, err := fileState.buildRace(buildCtx, cancelBuild, buildRaceParams)
if err != nil {
    log.Printf("error building race: %v", err)
}
// after
buildRaceResult, err := fileState.buildRace(buildCtx, cancelBuild, buildRaceParams)
if err != nil {
    var apiErr *shared.ApiError
    if errors.As(err, &apiErr) {
        activePlan.StreamDoneCh <- apiErr
        return
    }
    if errors.Is(err, context.Canceled) {
        return // user canceled, don't report as failure
    }
    log.Printf("error building race: %v", err)
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Pre-check inputs before entering the race path
if updated == "" || proposedContent == "" {
    return fmt.Errorf("cannot run build race with empty content")
}

Type guard

var apiErr *shared.ApiError
if errors.As(err, &apiErr) {
    // route to StreamDoneCh
    activePlan.StreamDoneCh <- apiErr
    return
}
if errors.Is(err, context.Canceled) {
    return // not a real failure
}

Try / catch

buildRaceResult, err := fileState.buildRace(buildCtx, cancelBuild, buildRaceParams)
if err != nil {
    var apiErr *shared.ApiError
    switch {
    case errors.As(err, &apiErr):
        activePlan.StreamDoneCh <- apiErr
    case errors.Is(err, context.Canceled):
        // swallow cancellation
    default:
        fileState.onBuildFileError(fmt.Errorf("error building race: %w", err))
    }
    return
}

Prevention

When it happens

Trigger: fileState.buildRace(buildCtx, cancelBuild, buildRaceParams) returns a non-nil error that is not *shared.ApiError — e.g. all racers in buildRace failed, LLM streaming call errored (network/timeout), or the repair candidates produced unusable output — while processing a file whose auto-apply had syntax errors or NeedsVerifyReasons.

Common situations: LLM provider outages or rate limits during the repair race, an invalid/expired auth token surfacing as a non-ApiError, malformed model responses that make every race branch fail, or context deadline exceeded on the build context.

Related errors


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