Read, Fix, and Test R Errors
Eleven short stations, one per common mistake. Do them in any order, then learn when and how to ask a person or an AI for help.
Every station on this page is independent. Each one opens with a line of code that is broken in one specific, common way. Run it as written to see what R says, then fix it, then check that the fix actually did what you meant. Stations do not share memory, so start anywhere and skip what you already know.
The first time you click Run Code, your browser downloads R once (a few seconds). After that it is quick.
| What you see | What it means | First move |
|---|---|---|
| Error in red, and nothing after it runs | R stopped. It could not do what you asked. | Find the name in quotes or backticks in the message. That is the thing R is complaining about. |
| Warning, plus output | R finished, but something looked wrong to it. | Treat the output as suspect until you understand the warning. |
No message, but the answer is NA, NULL, or 0 rows |
R did exactly what you typed. What you typed was not what you meant. | Check the result with nrow(), head(), or class() before you trust it. |
Fix one thing, run again, and see whether the message changes.
| R says | Usually means | Station |
|---|---|---|
object 'x' not found |
You never created x, you ran lines out of order, or you misspelled its name |
1 |
could not find function "x" |
A typo in the function name, or its package is not loaded | 2, 3 |
Unknown or uninitialised column: x (plus NULL) |
The column name is wrong, including capital letters and endings like _g |
4 |
unexpected ')', unexpected end of input, unexpected symbol, INCOMPLETE_STRING |
Unbalanced parentheses or quotes, or a missing comma | 5 |
We detected a named input ... Did you mean == |
You used = where == belongs |
6 |
argument is not numeric or logical: returning NA or non-numeric argument to binary operator |
Text where numbers were expected, often from quotes | 7 |
NA with no message |
Missing values, and you did not say what to do with them | 8 |
| 0 rows with no message | A comparison that matched nothing, often a capitalization mismatch | 9 |
The pipe operator requires a function call as RHS |
The function after |> is missing its () |
10 |
Keep this table. It works just as well in DataHub as it does here.
Station 1: object not found
See it. Someone wanted the average body mass of the penguins. Run the code exactly as written.
Decode it. R looked in memory for something called body_mass and found nothing. Either it was never created, or it exists under a different name. This is the most common error in the course, and it usually comes from running lines out of order.
Fix it. Make the line work. The weights are in a column of penguins. Use the scratch cell below to look at the column names if you need them. Then confirm the answer is a number, not NA.
- Which name in the message is one you typed? Does anything with that name exist yet?
exists("body_mass")will tell you. - Where do the weights live? Look at the output of
names(penguins). - There are two correct fixes: create
body_masswith<-before using it, or skip the middle step and pointmean()at the column directly withpenguins$....
body_mass <- penguins$body_mass_g
mean(body_mass, na.rm = TRUE)Or in one line: mean(penguins$body_mass_g, na.rm = TRUE). Both are right. Expect about 4,202 g.
Station 2: could not find function (typo)
See it. Run this as written.
Decode it. R has no function spelled exactly that way. Every letter and every capital counts: filter, Filter, and filtr are three different things to R, and only one of them keeps rows of a data frame.
Fix it. Correct the name. You should get 152 Adelie penguins.
- Which word in quotes in the message is one you typed?
- Compare it letter by letter with the dplyr verb for keeping rows.
?filteropens its help page. - A row count is a good check. Does the number you get make sense for one of three species in a 344-row dataset?
adelie <- filter(penguins, species == "Adelie")
nrow(adelie)152 rows. One missing letter was the whole problem.
Station 3: could not find function (package not loaded)
See it. The spelling here is fine. Run it anyway.
Decode it. Same message as Station 2, different cause. glimpse() lives in the dplyr package, and R does not know a package’s functions until you load it. A fresh R session, a new DataHub notebook, and this station all start knowing only base R.
Fix it. Load the package, then run the line again.
- Is the name spelled correctly? If so, the other cause of this message is a package that is not loaded.
- Which package does
glimpse()come from? What function loads a package? - Packages loaded in another station do not carry over here, the same way they do not carry over between R sessions.
library(dplyr)
glimpse(penguins)In DataHub, put every library() call at the top of your script. Then a restart never surprises you halfway through an analysis.
Station 4: wrong column name
See it. Run this as written and look closely at the output.
Decode it. Not red, but not right. The warning says there is no column called body_mass, and head() prints NULL, which means “nothing here.” Column names must match exactly, including endings like _g and _mm and every capital letter. In older code you may see R silently guess a partial name instead, which is worse.
Fix it. Use the real column name. You should see six numbers.
- What does
names(penguins)show for the body-mass column? Count the characters. NULLoutput after$is a column-name problem almost every time.
body_mass <- penguins$body_mass_g
head(body_mass)The column is body_mass_g. The _g is part of the name, not decoration.
Station 5: unbalanced parentheses and quotes
See it. This cell is missing one character. Run it and read the message.
Decode it. unexpected end of input means R reached the end of your code while still waiting for something, here a closing ). The ^ marker points at where R gave up. Related messages from the same family:
unexpected ')'means one)too many.unexpected symboloften means a missing comma between arguments.unexpected INCOMPLETE_STRINGmeans a quote was opened and never closed.
These are called syntax errors. R cannot even start running the code, so nothing in the cell happens.
Fix it. The exercise below has two separate syntax problems, one per line. Fix one, run, and read the new message before fixing the other. The exercise box on this page catches syntax errors before R does and shows a friendlier message than the one above; in DataHub you will see R’s version.
- On each line, count the
(and the). Count the"marks. Every opener needs a closer. - Inside a function call, what separates one argument from the next?
- Most editors, including DataHub’s RStudio, highlight the matching bracket when you click next to one. Use that.
adelie <- filter(penguins, species == "Adelie")
mean(adelie$body_mass_g, na.rm = TRUE)Line 1 was missing a closing ". Line 2 was missing the comma before na.rm. About 3,701 g.
Station 6: = where == belongs
See it. Run this as written and read the whole message, not just the first line.
Decode it. One = hands a value to a named argument. Two == asks a yes-or-no question: is species equal to "Adelie"? filter() needs the question. This message is unusually helpful: the lines marked with ℹ tell you exactly what went wrong and what to type instead. Many tidyverse messages do this, which is why reading past the first line pays off.
Fix it. You should get 152 rows.
- What does the last line of the message say to try?
- Where else in this course have you written
==? What question was it asking there?
filter(penguins, species == "Adelie")152 rows. When a message says “Did you mean …?”, it is usually right.
Station 7: numbers stored as text
See it. Three penguin weights were typed in with quotes around them. Run it as written.
Decode it. mean() gives a warning and returns NA because the quotes make these text, and R will not average words. The same mistake shows a different face elsewhere: weights_g + 100 is a red error, non-numeric argument to binary operator. Different messages, one cause. class(weights_g) tells you what R thinks you have.
Fix it. Make mean() return 3650. Either convert the text or enter the values as numbers.
- What does
class(weights_g)say? - What function turns
"3500"into3500? Its name starts withas.. - Or ask: do these values need quotes at all?
weights_g <- c("3500", "3800", "3650")
mean(as.numeric(weights_g))Or write weights_g <- c(3500, 3800, 3650) with no quotes. In real data this happens when a spreadsheet column contains a stray letter or comma; as.numeric() then converts what it can and returns NA for the rest, with a warning you should read.
Station 8: NA with no message
See it. No error, no warning. Run it and look at the answer.
Decode it. NA means “missing.” R will not average a set that contains an unknown, because the true answer is unknown too. It is being honest, not broken: the data have gaps, and you have to decide what to do about them. Skipping missing values is the usual choice, and you have to say so.
Fix it. You should get about 4,202 g. First, find out how many values are missing.
- How many weights are missing?
sum(is.na(penguins$body_mass_g))counts them. - Which argument of
mean()controls what happens to missing values??meanlists it. - A silent
NAis a sign to look at the data, not just the code.
mean(penguins$body_mass_g, na.rm = TRUE)Two penguins have no recorded weight. na.rm = TRUE removes them before averaging. The same argument works in median(), sd(), min(), and max().
Station 9: zero rows with no message
See it. Run it as written.
Decode it. Zero rows, and R did not complain. It compared text exactly, and "adelie" is not "Adelie". A filter that matches nothing is a silent failure: every mean downstream becomes NaN, every plot is blank, and nothing ever turns red. The only defense is to check the row count right after you filter.
Fix it. You should get 152.
- What are the exact species labels?
unique(penguins$species)shows them. - Compare capital letters, spaces, and spelling with what you typed.
adelie <- filter(penguins, species == "Adelie")
nrow(adelie)152 rows. Checking nrow() after every filter() is the habit that catches this.
Station 10: a pipe with no parentheses
See it. Run it as written.
Decode it. After |>, R needs a function call, which means parentheses. nrow is the function’s name; nrow() is the instruction to run it. The message says exactly this once you know that “RHS” means the right-hand side of the pipe. R catches this before running anything, so it belongs to the syntax-error family from Station 5.
Fix it. The same broken line is in the exercise box below. You should get 124 Gentoo penguins. (As in Station 5, the exercise box shows a friendlier syntax message than R’s until the line parses.)
- What is on the right-hand side of the last
|>? Is it a function call or just a function name? - Every other step in the chain has parentheses. Does the last one?
penguins |> filter(species == "Gentoo") |> nrow()124 rows. The older %>% pipe forgives this; the base |> pipe does not.
Getting help from a person
When the message and the table at the top of this page are not enough:
- Read the error again, out loud if you can. Find the name in quotes.
- Help pages:
?mean,?filter. Dense, but the Arguments section is usually what you need. - Web search: paste the exact error text in quotes, minus your own object names.
- Compare your line with one that works, from lecture, an earlier activity, or a classmate.
- Office hours, discussion board, instructor, or TA. Bring the code, the full message, and what you tried.
Try this with a partner. One person reads the error message aloud slowly; the other says which station it belongs to and what to try first. Swap roles. Saying the error out loud often makes the fix obvious.
Getting help from generative AI
Generative AI is good at explaining error messages in plain language, as long as you give it enough to work with and you stay in charge of the fix. What to paste, every time:
- Your code, the actual lines, not a description.
- The full message, copied, not retyped.
- What you were trying to do, in one sentence.
- What you already tried.
Ask for an explanation before you ask for a fix. Three prompts that keep you learning:
- “Explain this error message in plain language. What is R complaining about?”
- “Here is the line and what I want it to do. What is one thing to try, and why?”
- “How can I check that the fix did what I meant?”
A template you can copy (when your syllabus allows AI use):
I am a beginner learning R in an introductory biology course. Here is the code I ran, the full message, and what I was trying to do: [paste code], [paste message], [one-sentence goal]. I already tried [what you tried]. Explain what R is complaining about in plain language, suggest one thing to try, and tell me how to check that it worked. Use the Palmer Penguins dataset in any example. Do not write my graded assignment for me.
Rules that keep AI useful and honest:
- Run anything it suggests yourself. Code that reads well and code that works are different things.
- Verify the way the stations do:
nrow(),head(),class(), and whether the number makes biological sense. - Disclose AI use on assignments when the syllabus requires it.
Station 11: debug code an AI wrote
See it. A student asked an AI tool for the mean body mass of Gentoo penguins and pasted the answer straight in. Run it as written.
Decode it. The message is the one from Station 2, but there is no typo to fix: mean_na() does not exist. AI tools sometimes invent functions that sound plausible. The test is the same as for any other code: exists("mean_na") returns FALSE, and ?mean_na finds nothing. AI-written code fails in the same ways as human-written code, so every station on this page applies to it.
Fix it. Replace the invented function with a real one. You should get about 5,076 g.
- Which real function averages a vector? Which of its arguments skips missing values?
- Everything before the last
|>is fine. Only the last step needs to change.
penguins |>
filter(species == "Gentoo") |>
pull(body_mass_g) |>
mean(na.rm = TRUE)About 5,076 g. Red flags to look for in AI-written R: functions that do not exist, packages it never loads, column names from a different dataset, and na.rm quietly left out.
Course tools you can use
BILD 5 offers several AI-related resources. Your instructor or Canvas will show you where to find each one:
| Tool | What it is for |
|---|---|
| BILD5 bug checker chatbot | Course-specific help with R error messages and debugging steps |
| Schema Study | Socratic study coach for biology concepts, good for understanding what you are analyzing, not for pasting quiz or exam questions |
| Triton GPT | UC San Diego’s campus AI assistant for general help; still verify any code yourself and follow the course AI policy |
None of these replace running and testing your own code. They supplement the read, fix, and check loop you practiced above.
Recap
- Read the message. Find the name in quotes. Decide which of the three kinds of trouble it is: error, warning, or silent wrong answer.
- Fix one thing at a time.
- Check the result:
nrow()after a filter,head()orclass()on a column, and whether the number is biologically plausible. - Ask for help with the code, the full message, and what you tried.
Which station did you need the hint for? That is the one to redo without it.
Keep playing
Break this line on purpose, read the message, and fix it without looking at the hints. Try a typo in the column name, a missing ), a lowercase species name, or a dropped na.rm = TRUE. Before each run, predict which of the three kinds of trouble you will get.
- Column typo (
flipper_lenght_mm): a warning about an unknown column, thenNA(Station 4). - Missing
):unexpected end of input, a syntax error (Station 5). "chinstrap": no message, and the mean isNaNbecause zero rows were kept (Station 9).- Dropping
na.rm = TRUE: still a number here, because no Chinstrap flipper lengths are missing. Try it withbody_mass_gon all species instead (Station 8).