Fix 'missing value where TRUE/FALSE needed' in R
The error missing value where TRUE/FALSE needed means if() or while() received NA as its condition: a value arrived, but R does not know whether it is true or false. It usually traces back to an NA hiding in your data, a comparison written as x == NA, or an any() call that swallowed a missing value.
if (!is.na(x) && x > 5) "big" # rule out NA before comparing if (isTRUE(x > 5)) "big" # one call absorbs NA, NULL, empty is.na(x) # test for NA; x == NA never works if (any(x > 100, na.rm = TRUE)) "hit" # keep NA out of any() and all() x[!is.na(x)] # drop NAs before a loop colSums(is.na(df)) # find the NAs you did not expect
Need explanation? Read on for examples and pitfalls.
What this error means
if() needs a definite TRUE or FALSE, and you handed it a maybe. In R, NA marks a value that exists but is unknown: a survey answer left blank, a sensor that failed, a cell someone typed "n/a" into. R refuses to pick a branch based on an unknown, so it stops and reports exactly what it was missing.
The shortest way to trigger it is to test NA directly:
Real code rarely writes NA by hand. Instead, a comparison manufactures it. Any comparison involving NA returns NA, because if the input is unknown, the answer is unknown too:
That NA then flows into if(), and the error fires at the condition rather than at the true source of the missing value. The debugging job is always the same: find where the NA entered.
if (x > 5) fails with "object 'x' not found" when x does not exist, with "argument is of length zero" when x is NULL or empty, and with "missing value where TRUE/FALSE needed" when x is NA. Three similar-looking failures, three different bugs.The four causes and their fixes
Almost every occurrence comes from one of four patterns. Each subsection reproduces the failure, then shows the repair.
1. An NA in the data reaches the comparison
The most direct route: a column contains a missing value, and a condition tests the row that holds it:
Guard the comparison so NA takes a defined branch instead of crashing:
The && operator short-circuits: when !is.na(p) is FALSE, R never evaluates the risky right-hand side.
as.numeric(c("120", "n/a")) returns c(120, NA) with only a warning, and warnings are easy to miss in a long script. The crash then happens much later, at the first if() the value reaches. When this error appears right after importing or converting data, suspect coercion first.2. Testing for NA with == (it never works)
Many people hit this error while trying to handle NA, by writing the check the intuitive way:
== asks "are these two values equal?", and comparing anything with an unknown is unknown. Even NA == NA returns NA: two unknowns may or may not be equal. The only correct test is is.na():
3. any() or all() swallowed an NA
any() and all() look like safe wrappers, but they follow the same logic as comparisons. When no element settles the answer, a single NA makes the whole result NA:
No temperature exceeds 30, but the missing one might have, so any() refuses to say FALSE. Both functions take na.rm = TRUE to drop missing values before deciding:
4. A loop hits the NA row
This is the version that feels random: a loop runs fine for hundreds of iterations, then dies partway through. It worked until it met the missing value:
Note the 102 printed before the error: the first two iterations succeeded. Drop the missing values before looping, and the loop also reaches the 105 that sat beyond the crash point:
Why comparisons return NA
R treats NA as "unknown", and unknowns follow three-valued logic. An operation returns NA whenever the missing value could change the answer, and a definite result whenever it could not. That single rule explains every entry in this table:
| Expression | Result | Why |
|---|---|---|
NA > 5 |
NA |
Comparing with an unknown is unknown |
NA == NA |
NA |
Two unknowns may or may not be equal |
TRUE & NA |
NA |
The outcome depends on the unknown |
FALSE & NA |
FALSE |
FALSE and anything is FALSE |
any(c(FALSE, NA)) |
NA |
The NA could have been the TRUE |
all(c(TRUE, NA)) |
NA |
The NA could have been the FALSE |
The two & rows are worth running yourself, because they show NA is not simply contagious. When the known part already settles the answer, R gives it:
The same reasoning makes TRUE | NA return TRUE: one confirmed TRUE settles an OR no matter what the unknown turns out to be. Conditions built from && and comparisons inherit these rules, which is why the error can depend on which side of the condition R evaluates first.
if float("nan"): runs the true branch because NaN is truthy. SQL sits closer to R: NULL = NULL is not true, which is why SQL has IS NULL and R has is.na(). R is the strictest of the three, refusing to branch on an unknown at all.Find the NA that caused it
Work backward from the failing condition: some ingredient in it is NA. First confirm the suspect, then locate it:
For a whole data frame, one line counts the missing values per column and points at the one you did not know about:
In a long script, run traceback() immediately after the error to see which call contained the failing if(), then apply the checks above to that condition's inputs.
colSums(is.na(df)) line at the top of a script costs nothing and turns this error from a mid-run surprise into a known quantity you handle on your own terms.Try it yourself
Try it: The vector ex_scores holds four test scores, one of them missing. Set ex_top to TRUE if any score is above 90, ignoring the missing value, and print it. The wrong approach returns NA; yours should return a definite answer.
Click to reveal solution
Explanation: Without na.rm = TRUE, the comparison ex_scores > 90 contains an NA, and any() would return TRUE here only because 91 settles the answer; change 91 to 89 and it returns NA instead. na.rm = TRUE drops the missing value so the result is always a definite TRUE or FALSE.
FAQ
Is this the same error as "argument is of length zero"?
No, and telling them apart speeds up debugging. "Missing value where TRUE/FALSE needed" means the condition has exactly one element and it is NA: a value arrived, but it is unknown. "Argument is of length zero" means the condition has no elements at all, typically from NULL or an empty subset. The first sends you hunting for missing data; the second for a value that was never there.
Why does if (x == NA) fail even when x really is NA?
Because == cannot confirm equality with an unknown. x == NA evaluates to NA for every possible x, including when x is itself NA, so the condition is never TRUE or FALSE. The test you want is is.na(x), which returns a definite logical answer. This single substitution resolves a large share of real-world hits on this error.
How do I find which line or row triggers the error in a long script?
Run traceback() right after the error to see the call stack; the top entries show the if() that failed. Then inspect that condition's inputs with anyNA() and which(is.na(x)) to get the offending positions. For data frames, colSums(is.na(df)) gives a per-column missing count, and df[!complete.cases(df), ] shows the exact rows carrying the NAs.
Does ifelse() throw this error too?
No. ifelse() is vectorized and handles missing conditions by returning NA in those positions instead of stopping. That tolerance cuts both ways: the NAs pass through silently and surface later in results, plots, or models. if() crashing early is loud but honest; after switching to ifelse() or dplyr's if_else(), check the output for NAs you did not plan for.
Can while() loops raise it?
Yes, while() applies the same rule: its condition must evaluate to a single TRUE or FALSE on every iteration. A loop like while (total < 100) fails the moment total becomes NA, which commonly happens when arithmetic inside the loop touches a missing value, since total + NA is NA. Guard the update step with is.na() or clean the data the loop consumes.
Related R errors
Start with the parent guide, common R errors and how to read them. The official R documentation on NA specifies how missing values behave in every operation. For the closest sibling error, see argument is of length zero, which fires when the condition is empty rather than unknown. To deal with the missing values themselves, handling missing values in R covers detecting, counting, and imputing NAs, control flow in R explains what if, else, and while expect, and object not found covers the error you get when the variable itself is missing.