Skip to content

Rust Error E0624: Method Is Private

E0624 means: the method you called exists, but it was written without pub, so only code inside its module may call it. The struct can be public, and so can the module. Methods still start out private, one by one. It’s very common right after you move a type into its own module, and the fix is usually adding pub in front of fn. This page is part of the compiler errors guide.

error[E0624]: associated function `new` is private
--> src/main.rs:18:38
|
7 | fn new() -> Account { // no `pub`
| ------------------- private associated function defined here
...
18 | let mut account = bank::Account::new(); // ❌ private associated function
| ^^^ private associated function
error[E0624]: method `add_interest` is private
--> src/main.rs:19:13
|
11 | fn add_interest(&mut self) { // no `pub`
| -------------------------- private method defined here
...
19 | account.add_interest(); // ❌ private method
| ^^^^^^^^^^^^ private method

This is the program that produces it:

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
fn new() -> Account { // no `pub`
Account { balance: 0 }
}
fn add_interest(&mut self) { // no `pub`
self.balance += self.balance / 100;
}
}
}
fn main() {
let mut account = bank::Account::new(); // ❌ private associated function
account.add_interest(); // ❌ private method
}

rustc uses two names here. A method takes self (account.add_interest()). An associated function has no self and is called with :: (Account::new()). The rule and the fix are the same for both.

Each error has two arrows. The ^^^ arrow is your call. The --- arrow shows the fn line that’s missing pub. So the message tells you exactly where to add it.

Being inside impl Account doesn’t make a method public, even when Account is pub. Think of a restaurant: the menu is public, so you can order dishes (pub methods). The kitchen has its own steps, like “chop onions”, which you can’t ask for directly. Those are the private methods.

Everything in Rust is private by default, and methods are no exception (see Modules). Privacy belongs to the module where the impl block is written: any code in mod bank may call add_interest, and code outside may not.

This lets a type keep small helper methods that only make sense in the right order. Imagine add_interest should run once a month, after fees are charged. If anyone could call it, someone would call it twice by accident. Private helpers plus one public method that runs them correctly make that mistake impossible.

It also keeps your options open. Private methods can be renamed, merged or deleted any time, because the compiler guarantees no outside code uses them.

Choose this when the method is meant to be called from outside. For new this is almost always the case: a constructor nobody can call isn’t much use.

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
pub fn new(opening: u64) -> Account {
Account { balance: opening }
}
pub fn add_interest(&mut self) {
self.balance += self.balance / 100; // 1%
}
pub fn balance(&self) -> u64 {
self.balance
}
}
}
fn main() {
let mut account = bank::Account::new(1000);
account.add_interest();
println!("Balance: {}", account.balance());
}

Output:

Balance: 1010
▶ Try it Yourself

Fix 2: Call the public method that’s meant for you

Section titled “Fix 2: Call the public method that’s meant for you”

Choose this when the private method is a helper, especially in code you didn’t write. Often there’s a public method that calls it for you, in the right order and with the right checks. Here, keeping add_interest private is the correct design:

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
pub fn new(opening: u64) -> Account {
Account { balance: opening }
}
// The public way in: one call does the whole month, in the right order.
pub fn close_month(&mut self) {
self.charge_fee();
self.add_interest();
}
pub fn balance(&self) -> u64 {
self.balance
}
// Private helpers: calling them alone, or twice, gives wrong results.
fn charge_fee(&mut self) {
self.balance = self.balance.saturating_sub(5);
}
fn add_interest(&mut self) {
self.balance += self.balance / 100;
}
}
}
fn main() {
let mut account = bank::Account::new(1000);
account.close_month();
println!("After one month: {}", account.balance());
// account.add_interest(); // ❌ E0624: method `add_interest` is private
}

Output:

After one month: 1004
▶ Try it Yourself

A good rule: make a method pub only if calling it on its own, at any time can’t break the struct. If it only makes sense as one step of something bigger, keep it private and expose the bigger thing.

Fix 3: Use pub(crate) for “only my code”

Section titled “Fix 3: Use pub(crate) for “only my code””

Choose this when other modules of your crate need the method, but people using your library shouldn’t. pub(super) (only the parent module) works the same way; the E0603 page has a table of all the levels.

mod shop {
pub struct Cart {
prices: Vec<u32>,
}
impl Cart {
pub fn new() -> Cart {
Cart { prices: Vec::new() }
}
pub fn add(&mut self, price: u32) {
self.prices.push(price);
}
// For our own code only (like receipts), not for library users.
pub(crate) fn total(&self) -> u32 {
self.prices.iter().sum()
}
}
}
mod receipt {
pub fn print(cart: &crate::shop::Cart) {
println!("Total: {}", cart.total());
}
}
fn main() {
let mut cart = shop::Cart::new();
cart.add(3);
cart.add(5);
receipt::print(&cart);
}

Output:

Total: 8
▶ Try it Yourself

One catch: in a package with both src/lib.rs and src/main.rs, they are two crates. A pub(crate) fn total in lib.rs is private to main.rs:

error[E0624]: method `total` is private
--> src/main.rs:3:25
|
3 | println!("{}", cart.total());
| ^^^^^ private method
|
::: src/lib.rs:10:5
|
10 | pub(crate) fn total(&self) -> u32 {
| --------------------------------- private method defined here

There, use plain pub. See Cargo and crates.

Fix 4: Move the code that needs it into the module

Section titled “Fix 4: Move the code that needs it into the module”

Choose this when the method really should stay private, but some code needs it anyway, like an audit check or a test. Code in the same module can call it, and so can a child module: modules inside bank can see everything private in bank.

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
pub fn new(opening: u64) -> Account {
Account { balance: opening }
}
fn is_suspicious(&self) -> bool {
self.balance > 10_000
}
}
// A child module can use everything private in its parent.
pub mod audit {
pub fn check(account: &super::Account) -> &'static str {
if account.is_suspicious() { "please review" } else { "ok" }
}
}
}
fn main() {
let small = bank::Account::new(500);
let big = bank::Account::new(50_000);
println!("small: {}", bank::audit::check(&small));
println!("big: {}", bank::audit::check(&big));
}

Output:

small: ok
big: please review
▶ Try it Yourself

Unit tests work the same way. A mod tests written inside bank (or at the bottom of src/bank.rs) is a child module, so it may call private methods. See Testing:

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn not_suspicious_when_small() {
let account = Account::new(500);
assert!(!account.is_suspicious()); // private, but allowed here
}
}

An impl block in a different module. Privacy belongs to the module the impl is written in, not to the struct. If Order lives in mod model but you write impl Order { fn with_tax(&self) ... } inside mod pricing, then main gets method `with_tax` is private, pointing at mod pricing. Fix: pub fn with_tax, or pub(crate).

Using a method as a function value. accounts.iter().map(bank::Account::audit) is the same call written differently, so it gives the same E0624. Same fix.

Trait methods. You never write pub on methods inside impl SomeTrait for Type. They are as public as the trait, and adding pub is an error: error[E0449]: visibility qualifiers are not permitted here. If a trait method seems missing, you’ll get E0599 instead, and the fix is to use the trait.

A crate’s private method. You found the perfect method in a crate’s source code on GitHub, but it isn’t pub. You can’t call it, and its authors may change it in any release. Look for a public method that does the job on the crate’s page at docs.rs; only pub items appear there.

  • E0603: function `x` is private. The same idea for free functions, structs and modules.
  • E0616: field `x` of struct `Y` is private, when reading or writing a field.
  • E0451: a private field while building a struct with Y { ... }. Usually fixed by a pub fn new.
  • E0599: no method named `x` found. The method doesn’t exist for that type, or its trait isn’t in scope.
  • All compiler errors: the full list of error pages.

Quick check

1. pub struct Timer has impl Timer { fn start() -> Timer { ... } } inside mod clock. What happens when main calls clock::Timer::start()?

2. Which code may call a private method defined in mod bank?

3. A private add_interest must only run once a month, after fees. What's the best fix for E0624?

Score: 0 / 3