Missing ggplot2 aesthetics
Matches: geom_.* requires the following missing aesthetics
WHAT THIS ERROR MEANS
A ggplot2 geom layer requires certain aesthetic mappings (like x, y, fill, color) that you haven't provided.
WHY IT HAPPENS — 4 COMMON CAUSES
1. The geom needs an aesthetic you never supplied
Each geom declares required aesthetics. geom_point() needs both x and y; geom_histogram() needs only x because it computes the counts itself; geom_segment() needs four — x, y, xend and yend. The error names the ones it did not get.
2. The mapping went to the wrong layer
Aesthetics set in ggplot() are inherited by every layer; those set inside a geom apply only to it. Supplying aes() to the first geom and then adding a second geom that needs the same mapping leaves the second one with nothing.
3. aes() was placed outside the mapping argument
ggplot(df, aes(x, y)) is right; ggplot(df, x, y) is not. The second positional argument of ggplot() is mapping, so a bare column name there is passed as data rather than as an aesthetic.
4. inherit.aes = FALSE cut off the inheritance
Layers that set inherit.aes = FALSE — common when adding annotation data from a second data frame — deliberately ignore the plot-level aes(), so they must declare everything they need themselves.
HOW TO DIAGNOSE WHICH ONE IT IS
- Read the error: it names the missing aesthetics explicitly, as in "geom_point requires the following missing aesthetics: y".
- Check the geom’s documentation — ?geom_point lists required aesthetics in bold under the Aesthetics heading.
- Confirm where your aes() sits. Mappings in ggplot() are global; mappings inside a geom are local to it.
- Print the plot object’s mapping with p$mapping to see what the base layer actually carries.
- If a second data frame is involved, check whether that layer sets inherit.aes = FALSE.
HOW TO FIX IT
1. Add the required aesthetics inside aes().
2. Check the geom's documentation for required mappings.
3. Aesthetics can be set in ggplot() globally or in the specific geom.
CODE EXAMPLES
ggplot(df) + geom_point() # missing x and y
ggplot(df, aes(x = weight, y = height)) + geom_point()
MORE SCENARIOS THAT TRIGGER THIS
A second layer that does not inherit what it needs
ggplot(df) + geom_point(aes(x = date, y = revenue)) + geom_line() # Error: geom_line requires the following missing aesthetics: x and y
ggplot(df, aes(x = date, y = revenue)) + geom_point() + geom_line()
Moving the shared mapping up to ggplot() lets both layers inherit it. Keep mappings in a geom only when they genuinely differ between layers.
Setting a constant versus mapping a column
ggplot(df, aes(x = category, y = sales, colour = "blue")) + geom_col()
ggplot(df, aes(x = category, y = sales)) + geom_col(fill = "blue")
Anything inside aes() is treated as a column to map, so colour = "blue" creates a one-level variable named "blue" and a legend to match. Constants belong outside aes(), passed directly to the geom.
PACKAGE-SPECIFIC NOTES
ggplot2 3.4.0 renamed the size aesthetic to linewidth for line-based geoms, so older code using size on geom_line() now warns rather than errors. Note also that geoms with a computed stat need fewer mappings than you might expect: geom_histogram() and geom_bar() need only x because their stat generates y, and asking for y explicitly produces a different error about stat_count. To plot pre-computed totals instead, use geom_col(), which does take both.
FUNCTIONS WORTH KNOWING
aes()ggplot()geom_point()geom_col()labs()inherit.aesafter_stat()FREQUENTLY ASKED QUESTIONS
Why does geom_histogram() work with only x when geom_point() needs both?
geom_histogram() applies stat_bin(), which computes the counts and supplies y itself. Geoms that carry a computing stat require only the inputs that stat needs. geom_point() uses stat_identity() and plots your values as they are, so it needs both.
Should the mapping go in ggplot() or in the geom?
Put shared mappings in ggplot() so every layer inherits them, and reserve geom-level aes() for mappings that genuinely differ — a second series from another column, or a colour that applies to one layer only.
Why did colour = "red" inside aes() produce a legend instead of red points?
aes() maps data to visual properties, so it treated the string "red" as a single-level categorical variable, assigned it the first palette colour and drew a legend. To set a constant colour, pass it outside aes(), as geom_point(colour = "red").
Still stuck?
Paste your code in RChat and the AI will fix this error in context.