Angular Custom Async Validator stays in pending state
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When an Angular async validator never leaves PENDING, the validator function is usually not completing correctly. Angular expects an async validator to return a Promise or Observable that eventually resolves to either null or a validation error object, so anything that never emits, never completes, or throws without recovery can freeze the control in the pending state.
What Angular Expects From An Async Validator
An async validator is not just any asynchronous stream. Angular needs a final answer for the current validation run.
That answer must be one of two shapes:
- '
nullwhen the value is valid.' - An object such as
usernameTaken: truewhen invalid.
A typical validator using HttpClient looks like this:
The take(1) matters because it guarantees completion after one result.
Why Validators Get Stuck In PENDING
The most common cause is returning a stream that stays open forever. For example, using control.valueChanges inside the validator is a common trap because valueChanges is an ongoing stream, not a one-shot validation result.
Another cause is forgetting to emit null for valid input. If the validator only emits in the failure case and otherwise stays silent, Angular keeps waiting.
Errors can also leave the control effectively pending if the observable chain terminates unexpectedly and the code never maps the failure into a validation result.
Use The Validator On The Control Correctly
A reactive form setup usually looks like this:
Using updateOn: 'blur' is optional, but it often improves UX. Without it, Angular can launch a new async validation run on every keystroke, which may create a noisy sequence of overlapping network calls.
How To Debug It
If the control is stuck in PENDING, verify these points in order:
- Does the validator return an observable or promise every time?
- Does that async value emit exactly one result?
- Does it resolve to
nullor an error object? - Does it complete?
- Does the error path map to a value instead of breaking the chain?
If those conditions are true, Angular will usually leave PENDING correctly.
A related anti-pattern is subscribing inside the validator and calling setErrors manually later. Angular validators should describe validation as returned async state, not as side effects. Returning the observable directly keeps validation lifecycle and cleanup under Angular control.
Small validator design mistakes often show up first as a control that never leaves PENDING.
Common Pitfalls
One common mistake is returning control.valueChanges or another long-lived stream from inside the validator. Angular needs a one-shot result, not a subscription that stays alive forever.
Another mistake is forgetting completion. HttpClient observables complete naturally, but custom streams often do not unless you explicitly use operators such as take(1).
A third issue is swallowing server errors incorrectly. If the error path does not return of(null) or another valid result, the validator may fail without producing a final validation state.
Summary
- An Angular async validator must eventually return
nullor an error object. - Validators stay in
PENDINGwhen the returned async work never emits or never completes. - '
HttpClientplusmap,catchError, andtake(1)is a reliable pattern.' - Consider
updateOn: 'blur'to reduce unnecessary validation requests while the user is typing.

