Skip to content

Rust Error E0255: The Name Is Defined Multiple Times (Import vs Local Item)

E0255 means a use line and something you defined yourself have the same name. The classic case: you import std::io::Error at the top of the file, and later write your own enum Error. Rust can’t let one name mean two things, so it stops. It’s a very common error when you start writing your own error types, and the fix is one short line. Unlike E0412, this code hasn’t changed in recent releases: rustc 1.97 still reports it as E0255. It’s part of the compiler errors guide.

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` here
2 |
3 | enum Error { // ❌ same name as the import on line 1
| ^^^^^^^^^^ `Error` redefined here
|
= note: `Error` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
1 | use std::io::Error as OtherError;
| +++++++++++++
warning: unused import: `std::io::Error`
--> src/main.rs:1:5
|
1 | use std::io::Error;
| ^^^^^^^^^^^^^^

This is the program that produces it:

use std::io::Error;
enum Error { // ❌ same name as the import on line 1
EmptyName,
TooLong(usize),
}
fn check_name(name: &str) -> Result<(), Error> {
if name.is_empty() {
return Err(Error::EmptyName);
}
if name.len() > 10 {
return Err(Error::TooLong(name.len()));
}
Ok(())
}
fn main() {
match check_name("") {
Ok(()) => println!("name is fine"),
Err(Error::EmptyName) => println!("name is empty"),
Err(Error::TooLong(n)) => println!("name has {} letters, max is 10", n),
}
}

rustc points at three things:

  1. The --- line (line 1): “previous import of the type Error here”. The use line already put a name Error into this module.
  2. The ^^^ line (line 3): “Error redefined here”. Your own enum Error tries to take the same name.
  3. The help: offers a way out: give the import a different local name with as.

The warning: unused import below it is a useful clue. It means nothing in your code really uses std::io::Error (every Error in this program means your enum). In that case you can simply delete line 1. If you do need both, keep reading.

The note mentions the type namespace. Types, traits and modules share one list of names; functions, constants and statics share another. So use std::mem::swap; plus your own fn swap is the same error, but in the “value namespace”.

Think of a classroom with two pupils called Alex. The teacher can’t just call “Alex” anymore. Someone needs a nickname, like “Alex B.”, and that’s exactly what as gives an import.

A name in a module points at exactly one item. When Rust reads Error::EmptyName on line 10, it has to know which Error you mean, and it refuses to guess. If it quietly picked your enum, your use line would do nothing; if it picked io::Error, your enum would be unreachable. Either way, a silent choice would hide a mistake.

That’s why E0255 is a sibling of E0428 (two of your own items with one name) and E0252 (two use lines with one name). The rule is the same: one name, one thing, per module. See Modules for how use works.

Choose this when you need both types in the same file, which is common: your own Error for your app’s rules, and io::Error for files and the network. Give the import a nickname that says where it comes from. IoError reads better than rustc’s placeholder OtherError:

use std::io::Error as IoError;
use std::io::ErrorKind;
#[derive(Debug)]
enum Error {
EmptyName,
TooLong(usize),
}
fn check_name(name: &str) -> Result<(), Error> {
if name.is_empty() {
return Err(Error::EmptyName);
}
if name.len() > 10 {
return Err(Error::TooLong(name.len()));
}
Ok(())
}
fn save_name(name: &str) -> Result<(), IoError> {
if name == "root" {
return Err(IoError::new(ErrorKind::PermissionDenied, "that name is reserved"));
}
Ok(())
}
fn main() {
println!("{:?}", check_name("Ferris"));
println!("{:?}", check_name(""));
println!("{:?}", check_name("Ferris the Crab"));
match save_name("root") {
Ok(()) => println!("saved"),
Err(e) => println!("io error: {}", e),
}
}

Output:

Ok(())
Err(EmptyName)
Err(TooLong(15))
io error: that name is reserved
▶ Try it Yourself

as only changes the name in this file. Everywhere else, the type is still std::io::Error.

Choose this when you’d like each Error to show where it comes from at every use. Import the parent module with use std::io; and write io::Error. Your own Error keeps the short name. Many Rust programmers prefer this style for types with common names like Error and Result:

use std::io;
enum Error {
EmptyName,
}
fn check_name(name: &str) -> Result<(), Error> {
if name.is_empty() {
return Err(Error::EmptyName);
}
Ok(())
}
fn save_name(name: &str) -> Result<(), io::Error> {
if name == "root" {
return Err(io::Error::new(io::ErrorKind::PermissionDenied, "reserved name"));
}
Ok(())
}
fn main() {
if let Err(Error::EmptyName) = check_name("") {
println!("name is empty");
}
if let Err(e) = save_name("root") {
println!("io error: {}", e);
}
}

Output:

name is empty
io error: reserved name
▶ Try it Yourself

Choose this when your type will be used in many files, or by other people. A specific name like NameError or AppError is clearer than a second Error, and the use line can stay as it is:

use std::io::Error;
#[derive(Debug)]
enum NameError {
EmptyName,
TooLong(usize),
}
fn check_name(name: &str) -> Result<(), NameError> {
if name.is_empty() {
return Err(NameError::EmptyName);
}
if name.len() > 10 {
return Err(NameError::TooLong(name.len()));
}
Ok(())
}
fn main() {
println!("{:?}", check_name("Ferris the Crab"));
let disk = Error::other("disk is full");
println!("{}", disk);
}

Output:

Err(TooLong(15))
disk is full
▶ Try it Yourself

For bigger projects, the thiserror crate makes such error enums much shorter to write. See Custom Errors.

Choose this when rustc also prints warning: unused import, like in the error above. The import is left over from earlier code, or was added by your editor. Remove the line, and the program from the top of this page works as written:

enum Error {
EmptyName,
TooLong(usize),
}
fn check_name(name: &str) -> Result<(), Error> {
if name.is_empty() {
return Err(Error::EmptyName);
}
if name.len() > 10 {
return Err(Error::TooLong(name.len()));
}
Ok(())
}
fn main() {
match check_name("") {
Ok(()) => println!("name is fine"),
Err(Error::EmptyName) => println!("name is empty"),
Err(Error::TooLong(n)) => println!("name has {} letters, max is 10", n),
}
}

Output:

name is empty
▶ Try it Yourself

Your own function with a std name. use std::mem::swap; plus fn swap(a: &mut i32, b: &mut i32) gives E0255 with “previous import of the value swap here” and the note “value namespace”. Fix: call yours swap_values, or drop the import if you meant to write your own.

Copy-paste between modules. You move struct User into mod models, add use models::User; at the top, but forget to delete the old struct User in main.rs. Fix: delete the old copy, so User means only the one in models.

A trait with a std name. use std::fmt::Display; and your own trait Display clash the same way (“previous import of the trait Display”). Fix: rename your trait (Describe, Render), or write use std::fmt; and fmt::Display.

Good to know: a glob import like use std::io::*; never causes E0255. Your own items quietly win over names that come in through a *. That’s handy, but it can also hide which Error you’re using, so explicit imports are usually clearer.

  • E0252: two use lines bring in the same name, like fmt::Result and io::Result.
  • E0428: two of your own items share a name, often from trying to overload a function.
  • E0592: two methods with the same name in an impl block.
  • E0432: the use line itself points at something that doesn’t exist.
  • E0425: the opposite problem: a name that isn’t defined at all where you use it.
  • All compiler errors: the full list of error pages.

Quick check

1. Your file starts with use std::fmt::Result; and later defines enum Result { Pass, Fail }. Which error do you get?

2. You need both std::io::Error and your own enum Error in one file. What's a clean fix?

3. rustc shows E0255 and also warning: unused import: std::io::Error. What does the warning tell you?

Score: 0 / 3