Skip to content
Select theme

How to fix error E0106: missing lifetime specifier

Short answer: a reference appears in a signature — a return type or a struct field — and the compiler cannot tell from the signature alone what it will borrow from. Nothing is wrong with the body; the contract is incomplete. The usual fix is to name a lifetime ('a) and write the relationship down. Sometimes there is nothing to borrow from at all, and the right fix is not a lifetime but an owned type. E0597 is the compiler checking a lifetime you wrote and rejecting it; E0106 is the earlier moment, before there is anything to check.

The everyday version: a function takes two references and returns one of them.

Compiling that with cargo build prints:

error[E0106]: missing lifetime specifier
--> src/main.rs:1:33
|
1 | fn longest(x: &str, y: &str) -> &str {
| ---- ---- ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
help: consider introducing a named lifetime parameter
|
1 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
| ++++ ++ ++ ++
For more information about this error, try `rustc --explain E0106`.

The headline is short because the problem is not in the code the compiler can see — it is in the part the signature left out. The help says it plainly: the return type contains a borrowed value, but the signature does not say whether it is borrowed from x or y. Both are plausible — the function returns one of them, chosen at run time — and a caller holding the result deserves to know until when it stays valid. References are promises about how long data stays alive; this signature makes a promise the compiler cannot check.

The fix is to name the lifetime and say which inputs share it:

This prints:

Call me Ishmael

'a is a name for the region the two inputs and the return all share: both arguments must live at least that long, and the returned reference is valid for exactly that long — no longer than the shorter-lived of the two. Nothing changed at run time. No value is created, copied, or kept alive; the annotation only writes down what a caller may rely on. That is why E0106 feels unlike most errors: the code already worked. The signature just did not say so.

If every function returning a reference needed this, 'a would be everywhere. It is not, because the compiler fills in the common cases by itself:

This prints:

best

No lifetime, no error: one input reference, so the output’s lifetime is the input’s — there is nothing else it could be. The other automatic case is a method whose output borrows from &self. The rules the compiler applies here are called elision, and E0106 is what shows up when elision cannot decide: two or more input references (which one does the return borrow from?), or none (what would it borrow from at all?). Then the compiler needs to be told. The full rules are the subject of the Lifetimes chapter; this page stays on the error.

Same error, second home: a struct field that is a reference.

Compiling that with cargo build prints:

error[E0106]: missing lifetime specifier
--> src/main.rs:2:11
|
2 | text: &str,
| ^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
1 ~ struct Excerpt<'a> {
2 ~ text: &'a str,
|
For more information about this error, try `rustc --explain E0106`.

Note where the pointer lands: not at the call site in main, but at the field itself. A struct containing a reference promises that every instance borrows its text from data that outlives the instance — and the definition has to say what that region is called, because the compiler cannot check a promise it has not seen. The help writes the fix for you:

This prints:

Call me Ishmael

Now the struct is generic over a lifetime: an Excerpt<'a> holds a &'a str, so an instance cannot outlive the data its text came from. The main above is legal because novel lives to the end of the block, longer than e. Dropping novel first, or letting the borrow escape past it, is where E0597-style errors begin — but that is a different page. E0106 only ever says the signature is incomplete.

The third shape has no honest fix in the signature, and the compiler’s own help: is a trap. A function returns a reference, but every value inside it is local:

Compiling that with cargo build prints:

error[E0106]: missing lifetime specifier
--> src/main.rs:1:15
|
1 | fn badge() -> &str {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
1 | fn badge() -> &'static str {
| +++++++
help: instead, you are more likely to want to return an owned value
|
1 - fn badge() -> &str {
1 + fn badge() -> String {
|
For more information about this error, try `rustc --explain E0106`.

This time the help offers two doors, and it says which one is uncommon. The 'static door silences E0106 and just moves the error: with &'static str as the return type, the body fails instead, because s does not live for the whole program:

error[E0515]: cannot return reference to local variable `s`
--> src/main.rs:3:5
|
3 | &s
| ^^ returns a reference to data owned by the current function
For more information about this error, try `rustc --explain E0515`.

The truth E0106 was hiding is now on the table: there is nothing for the returned reference to point at. No annotation can create data to borrow from — which is what the second help: line already said. The fix is to return the owned value:

This prints:

nothing to borrow from

The caller owns the String and can borrow from it afterwards if it needs to. The one case where 'static really is the answer is a value that is part of the program itself — a string literal, for instance, which lives for the whole run:

This prints:

nothing to borrow from

That works because the literal is baked into the binary, not because a lifetime rescued a local.

  • A return type with two or more input references — the signature does not say which input the return borrows from. Name 'a, tie the return and the inputs it borrows from to it.
  • A struct field that is a reference — the struct never declared what it borrows from. Add a lifetime parameter to the struct, exactly like a type parameter.
  • A return type with no input references — there is nothing to borrow from, and no lifetime fixes it. Return an owned type, or return a &'static str if the value is genuinely constant.

The help: block decides it: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from ... is the first shape, consider introducing a named lifetime parameter is the second, and there is no value for it to be borrowed from is the third — the one where the help itself says the likely fix is not a lifetime at all.

  • borrowed value does not live long enough — E0597, the compiler checked a lifetime you wrote and refused it. E0106 happens before any checking: there is no lifetime to check yet.
  • temporary value dropped while borrowed — E0716, the same story with a temporary instead of a named local.