Rust Error E0428: The Name Is Defined Multiple Times
E0428 means you defined two things with the same name in the same place: two functions called area, two structs called User, or an enum and a struct both called Status. It often happens when you try to overload a function, the way you would in Java, C# or C++. Rust doesn’t have overloading, but it has good replacements, and this page shows them. It’s part of the compiler errors guide.
The error message
Section titled “The error message”error[E0428]: the name `area` is defined multiple times --> src/main.rs:5:1 |1 | fn area(width: f64, height: f64) -> f64 { | --------------------------------------- previous definition of the value `area` here...5 | fn area(radius: f64) -> f64 { // ❌ a second `area` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `area` redefined here | = note: `area` must be defined only once in the value namespace of this moduleThis is the program that produces it:
fn area(width: f64, height: f64) -> f64 { width * height}
fn area(radius: f64) -> f64 { // ❌ a second `area` 3.14159 * radius * radius}
fn main() { println!("{}", area(2.0, 3.0)); println!("{}", area(1.0));}rustc also prints a second error for this program: E0061, “this function takes 2 arguments but 1 argument was supplied”, on area(1.0). That’s only a side effect. Rust kept the first area and ignored the second, so the one-argument call no longer fits. Fix E0428 and E0061 goes away with it.
What it means
Section titled “What it means”rustc points at two places:
- The
---line (line 1): “previous definition of the valueareahere”. This is the firstarea, the one Rust keeps. - The
^^^line (line 5): “arearedefined here”. This is the second one, and it’s the one that’s rejected. - The
note:saysareamust be defined only once “in the value namespace of this module”. Each module is like one drawer, and inside a drawer every name must be unique.
For two structs, the note says “type namespace” instead. Rust keeps types (structs, enums, traits, modules) and values (functions, constants, statics) in two separate lists. That’s why a mod shapes and a fn shapes can live side by side, but two fn area or two struct User can’t.
Think of two files called report.txt in one folder. Your computer refuses the second one, not because something is wrong with it, but because report.txt would no longer tell it which file you mean.
Why Rust does this
Section titled “Why Rust does this”In Rust, a name in a module points at exactly one item. When you write area(...), Rust finds the function by its name alone, not by the number or types of the arguments. That keeps things simple to read: there’s only one area to look up, and adding a new function can never quietly change which one an old call uses.
Languages with overloading pick the version from the arguments, and the rules get tricky once numbers convert into each other or default values join in. Rust chose not to do that. When you want “the same name for different inputs”, you use traits or generics, where the choice is visible in the types. More on functions in Functions.
How to fix it
Section titled “How to fix it”Fix 1: Give each one its own name
Section titled “Fix 1: Give each one its own name”Choose this most of the time. Two functions that take different inputs usually do different jobs, and the name can say which. If one of them was an old copy you forgot to delete, delete it instead:
fn rectangle_area(width: f64, height: f64) -> f64 { width * height}
fn circle_area(radius: f64) -> f64 { 3.14159 * radius * radius}
fn main() { println!("{}", rectangle_area(2.0, 3.0)); println!("{}", circle_area(1.0));}Output:
63.14159The standard library does the same: String::new(), String::with_capacity(10) and String::from("hi") are three different names for three ways to make a String.
Fix 2: Put them in separate modules
Section titled “Fix 2: Put them in separate modules”Choose this when the short name really is the best name in each context, like area for each shape, or a User in your database code and a different User in your API code. Each module has its own names, so the clash disappears. Callers write the module name in front:
mod rectangle { pub fn area(width: f64, height: f64) -> f64 { width * height }}
mod circle { pub fn area(radius: f64) -> f64 { 3.14159 * radius * radius }}
fn main() { println!("{}", rectangle::area(2.0, 3.0)); println!("{}", circle::area(1.0));}Output:
63.14159Don’t forget pub, or the call from main gives E0603, “function is private”. See Modules.
Fix 3: Use a trait instead of overloading
Section titled “Fix 3: Use a trait instead of overloading”Choose this when you want one call that works for many types, which is what overloading is usually for. Make a type for each kind of input, and give them a shared trait. Now every shape has its own area, and Rust picks the right one from the value’s type:
trait Shape { fn area(&self) -> f64;}
struct Rectangle { width: f64, height: f64,}
struct Circle { radius: f64,}
impl Shape for Rectangle { fn area(&self) -> f64 { self.width * self.height }}
impl Shape for Circle { fn area(&self) -> f64 { 3.14159 * self.radius * self.radius }}
fn print_area<T: Shape>(shape: &T) { println!("Area: {}", shape.area());}
fn main() { print_area(&Rectangle { width: 2.0, height: 3.0 }); print_area(&Circle { radius: 1.0 });}Output:
Area: 6Area: 3.14159This is more code than Fix 1, so it pays off when you have several shapes or several functions (area, perimeter, draw) that all follow the same pattern. The generic print_area<T: Shape> works for any shape you add later. See Traits and Generics.
For “the same function with or without an extra argument”, there’s a lighter option: take an Option, like fn greet(name: &str, title: Option<&str>), and call it with None or Some("Dr.").
Fix 4: Rename an import with use ... as ...
Section titled “Fix 4: Rename an import with use ... as ...”Choose this when the clash is between your own item and a use line. Strictly speaking that’s a sibling error, E0255, with the same headline:
error[E0255]: the name `Error` is defined multiple times --> src/main.rs:3:1 |1 | use std::io::Error; | -------------- previous import of the type `Error` here2 |3 | enum Error { | ^^^^^^^^^^ `Error` redefined here | = note: `Error` must be defined only once in the type namespace of this modulehelp: you can use `as` to change the binding name of the import |1 | use std::io::Error as OtherError; | +++++++++++++Give the import a local nickname with as. Pick a name that says where it comes from, like IoError, rather than rustc’s placeholder OtherError:
use std::io::Error as IoError;use std::io::ErrorKind;
#[derive(Debug)]enum Error { NotFound(String), Invalid(u32),}
fn main() { let mine = Error::NotFound(String::from("config.toml")); let other = Error::Invalid(42); let disk = IoError::new(ErrorKind::Other, "disk is full");
println!("{:?}", mine); println!("{:?}", other); println!("{}", disk);}Output:
NotFound("config.toml")Invalid(42)disk is fullTwo use lines that clash, like use std::fmt::Result; and use std::io::Result;, give a third sibling, E0252 (`Result` reimported here). The fix is the same: use std::io::Result as IoResult;, or import the module (use std::io;) and write io::Result. Renaming your own enum (AppError) works too.
Where you’ll usually see it
Section titled “Where you’ll usually see it”Overloading a method in an impl block. Two fn new in impl Timer give a different code, E0592: duplicate definitions with name `new` . Same cause, same fix: name them for what they do, like Timer::new() and Timer::with_seconds(30). See Structs.
Copy-paste while refactoring. You copy a function to change it, or paste a struct User from another file, and forget to remove the old one. Also common in tests: two #[test] fn it_works() in one mod tests give E0428. Fix: delete the old copy, or rename the test.
Duplicate enum variants. enum Color { Red, Red } gives E0428 too, pointing at the second Red, with the note “type namespace of this enum”. Fix: remove or rename the duplicate variant. See Enums.
Related errors
Section titled “Related errors”- E0061: wrong number of arguments. Often printed right after E0428 when you tried to overload a function.
- E0425: the opposite problem: a name that’s defined zero times where you use it.
- E0433: a path like
circle::areawhose first part (the module) can’t be found. - E0034: two traits give a type methods with the same name; you need to say which one you mean.
- E0255 (a
useclashes with a local item), E0252 (twouselines clash), E0592 (duplicate method in animpl): the siblings shown above. - All compiler errors: the full list of error pages.
Quick check
Section titled “Quick check”Quick check
1. You write fn total(a: u32) and fn total(a: u32, b: u32) in one file. What happens?
2. Can mod report and fn report() live in the same module?
3. Your file has use std::fmt::Result; and you define enum Result. What's a clean fix?
Score: 0 / 3
Read more
Section titled “Read more”- E0428 — Rust error codes index: the official explanation, with the two-structs example.
- Defining Modules to Control Scope and Privacy — The Rust Book: how modules give each part of your code its own names.
- Providing New Names with the
asKeyword — The Rust Book: thefmt::Resultandio::Resultexample, solved withas. - Traits — The Rust Book: sharing behavior between types, the Rust answer to overloading.
- Namespaces — The Rust Reference: the exact rules for the type and value namespaces mentioned in the error’s note.