plandex-ai/plandex · warning

fast apply validation failed: %s

Error message

fast apply validation failed: %s

What it means

The validation loop completed but reported validateResult.valid == false with a human-readable validateResult.problem; the problem text is wrapped into this error and stored in builderRun.FastApplyFailureResponse. It means the fast-apply output was syntactically valid but semantically/structurally rejected by validation, so the race falls back via onFail() to the whole-file build.

Source

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

				if errors.Is(err, context.Canceled) {
					log.Printf("Context canceled during fast apply validation")
					return
				}

				log.Printf("buildRace - fast apply validation failed with error: %v", err)
				sendErr(fmt.Errorf("fast apply validation failed: %w", err))
				onFail()
				return
			}

			if validateResult.valid {
				log.Printf("buildRace - fast apply validation succeeded")
				fileState.builderRun.FastApplySuccess = true
				sendRes(raceResult{content: validateResult.updated, valid: validateResult.valid})
			} else {
				log.Printf("buildRace - fast apply validation failed with problem: %s", validateResult.problem)
				fileState.builderRun.FastApplyFailureResponse = validateResult.problem
				sendErr(fmt.Errorf("fast apply validation failed: %s", validateResult.problem))
				onFail()
				return
			}
		}()
	}

	startFallbacks := func(comments string) {
		startedFallbacks = true
		// try fast apply + validation first if it's defined
		// if it's undefined or fails, start the whole file build fallback
		maybeStartFastApply(func() {
			startWholeFileBuild(comments)
		})
	}

	// If we get an incorrect marker, start the whole file build in the background while the validation/replacement loop continues
	onInitialStream := func(chunk string, buffer string) bool {
		if !startedFallbacks && strings.Contains(buffer, "<PlandexIncorrect/>") && strings.Contains(buffer, "<PlandexComments>") {

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read builderRun.FastApplyFailureResponse / validateResult.problem for the rejection reason
  2. Let the built-in fallback proceed — onFail() starts the whole-file rebuild automatically
  3. Reduce fast-apply scope (smaller, targeted edits) so validation is more likely to pass
  4. Improve the fast-apply prompt/constraints so output matches the described change exactly
Defensive patterns

Strategy: validation

Validate before calling

if validateResult == nil || (!validateResult.valid && validateResult.problem == "") {
	log.Printf("validation returned invalid result without a problem description")
	onFail()
	return
}

Type guard

func validationPassed(vr *buildValidateResult) bool {
	return vr != nil && vr.valid
}

Try / catch

if !validationPassed(validateResult) {
	fileState.builderRun.FastApplyFailureResponse = validateResult.problem
	sendErr(fmt.Errorf("fast apply validation failed: %s", validateResult.problem))
	onFail()
	return
}
sendRes(raceResult{content: validateResult.updated, valid: validateResult.valid})

Prevention

When it happens

Trigger: buildValidateLoop (maxAttempts:1, validate-only) returns a result whose valid field is false — e.g. the applied edit does not satisfy the requested change, leaves unresolved markers, or fails the model's validation criteria.

Common situations: Fast-apply patch applies cleanly but misses part of the requested change; leftover replacement markers in the output; edit context drifted from the original file so the result no longer matches intent; overly aggressive fast-apply on large multi-hunk changes.

Related errors


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