Rust Error E0554: #![feature] May Not Be Used on the Stable Release Channel
E0554 means: your code starts with a #![feature(...)] line, and only the nightly version of Rust accepts those. You almost always get it from code you copied: a blog post, a GitHub repo, an AI answer, an old Stack Overflow reply. That code was written for nightly Rust, and you’re on stable, which is what rustup installs by default. Nothing is wrong with your setup. The fix is usually to delete one line and use a stable way to do the same thing. (This page is part of Rust compiler errors explained.)
The error message
Section titled “The error message”error[E0554]: `#![feature]` may not be used on the stable release channel --> src/main.rs:1:1 |1 | #![feature(iter_map_windows)] // ❌ copied from code written for nightly Rust | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^This is the program that produces it:
#![feature(iter_map_windows)] // ❌ copied from code written for nightly Rust
fn main() { let temps = [18, 21, 19, 24]; let changes: Vec<i32> = temps.iter().map_windows(|[a, b]| *b - *a).collect(); println!("{:?}", changes);}What it means
Section titled “What it means”The ^^^ underlines the whole first line, #![feature(iter_map_windows)]. That line is a request: “please switch on the unfinished feature called iter_map_windows.” Only the nightly compiler takes such requests. The “stable release channel” in the message is the normal Rust you get from rustup, and it refuses.
Notice what rustc does not complain about: map_windows on line 5. It stops at the #![feature] line first. Once you remove that line, you’ll find out whether the rest of the code works on stable.
You get the same error on the beta channel. If your code has several #![feature] lines, rustc usually reports only the first one, so check the top of the file for more.
It’s like a “staff only” pass. The test kitchen (nightly) lets you in with it. The restaurant (stable) doesn’t accept those passes at all, however politely you show it.
Why Rust does this
Section titled “Why Rust does this”Rust promises that code which compiles on stable today keeps compiling on every future stable 1.x release. Unfinished features can’t be part of that promise: their names, arguments and behaviour can still change, or they can be removed. So they live only on nightly, a new build of the compiler made every night, and you switch each one on by name with #![feature(...)].
Stable Rust doesn’t just ignore the line: it stops with an error. That way you can’t build a project on an unfinished feature without noticing. When a feature is finished, it becomes part of stable Rust and no longer needs the line at all.
So when you see E0554, there are only three real questions: is there a stable way to do this (Fix 1), is the feature already stable (Fix 2), or do you really want nightly (Fix 3)? See Stable, beta and nightly.
How to fix it
Section titled “How to fix it”Fix 1: Remove the attribute and use the stable API
Section titled “Fix 1: Remove the attribute and use the stable API”Choose this almost every time. Delete the #![feature] line and compile again. If you now get E0658 (use of unstable library feature `iter_map_windows` ), the feature is still unfinished, and you need a stable way to do the same thing. Most unstable methods are shortcuts for something stable Rust can already do. Here, .windows(2) on a slice gives you each pair of neighbours:
fn main() { let temps = [18, 21, 19, 24]; let changes: Vec<i32> = temps.windows(2).map(|w| w[1] - w[0]).collect(); // ✅ stable println!("{:?}", changes);
for w in temps.windows(2) { println!("{} -> {}", w[0], w[1]); }}Output:
[3, -2, 5]18 -> 2121 -> 1919 -> 24To find the stable way, open the method in the standard library docs. Unstable items have a box that says “This is a nightly-only experimental API”, and the feature name in your #![feature] line usually matches a page in The Unstable Book. See Slices and Iterators.
Fix 2: Check whether the feature is stable now
Section titled “Fix 2: Check whether the feature is stable now”Choose this when the code is a bit older. Many features that once needed #![feature] are now part of stable Rust, and then the line is simply not needed any more. rustc tells you so in a warning right below the error:
error[E0554]: `#![feature]` may not be used on the stable release channel --> src/main.rs:2:1 |2 | #![feature(slice_as_chunks)] // ❌ not needed any more: this feature is stable now | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: the feature `slice_as_chunks` has been stable since 1.88.0 and no longer requires an attribute to enable --> src/main.rs:2:12 |2 | #![feature(slice_as_chunks)] // ❌ not needed any more: this feature is stable now | ^^^^^^^^^^^^^^^The broken program:
// Copied from an older tutorial#![feature(slice_as_chunks)] // ❌ not needed any more: this feature is stable now
fn main() { let pixels = [255, 0, 0, 0, 128, 255]; let (rgb, _rest) = pixels.as_chunks::<3>(); for [r, g, b] in rgb { println!("r={} g={} b={}", r, g, b); }}Delete the #![feature] line (and the comment above it) and the rest works unchanged:
fn main() { let pixels = [255, 0, 0, 0, 128, 255]; let (rgb, _rest) = pixels.as_chunks::<3>(); // ✅ stable since Rust 1.88 for [r, g, b] in rgb { println!("r={} g={} b={}", r, g, b); }}Output:
r=255 g=0 b=0r=0 g=128 b=255For language features, rustc is even more direct and adds help: remove the attribute under the error, plus a line like the feature `async_closure` has been stable since `1.85.0` and no longer requires an attribute to enable.
No warning, but you suspect the feature is stable? Your Rust may simply be older than the version where it became stable. Check and update:
rustc --versionrustup updateIf rustc --version still shows an old version afterwards, the project probably has a rust-toolchain.toml file that pins it. See Pinning a toolchain per project.
Fix 3: Use nightly on purpose
Section titled “Fix 3: Use nightly on purpose”Choose this last, when there is no stable way and you accept that your code may break with a future nightly. Typical good reasons: you’re trying out a new feature, writing a small experiment, or the project you’re contributing to already uses nightly. Install nightly next to stable and use it for one command:
rustup toolchain install nightlycargo +nightly runOr make the whole project use nightly with a rust-toolchain.toml file next to Cargo.toml. Then plain cargo run picks nightly in that folder, and stable everywhere else:
[toolchain]channel = "nightly"For a project other people build too, pin a date, like channel = "nightly-2026-10-01", so everyone gets the same compiler. On the Rust Playground, choose Nightly in the toolchain menu.
You may find advice to set RUSTC_BOOTSTRAP=1 to make stable accept #![feature]. That switch exists for building the Rust compiler itself. Using it gives you all the risks of nightly while pretending to be on stable, so don’t.
Where you’ll usually see it
Section titled “Where you’ll usually see it”Benchmarks with #[bench]. Old guides write benchmarks like this, and #![feature(test)] is still nightly-only:
error[E0554]: `#![feature]` may not be used on the stable release channel --> src/main.rs:3:1 |3 | #![feature(test)] // ❌ built-in benchmarks are nightly-only | ^^^^^^^^^^^^^^^^^//! Price helpers.//! Benchmark written the old way, for nightly Rust.#![feature(test)] // ❌ built-in benchmarks are nightly-onlyextern crate test;
fn total(prices: &[u32]) -> u32 { prices.iter().sum()}
#[bench]fn bench_total(b: &mut test::Bencher) { let prices: Vec<u32> = (1..1000).collect(); b.iter(|| total(&prices));}
fn main() { println!("{}", total(&[3, 4, 5]));}Fix: use a benchmarking crate that works on stable, like criterion or divan, and run cargo bench. Deleting only the #![feature] line isn’t enough here: extern crate test; then gives E0658 (use of unstable library feature `test` ). See Performance.
A dependency that needs nightly. If the --> line points into a crate under ~/.cargo/registry/ instead of your own src/, it’s a crate you depend on that uses #![feature]. Fix: check the crate’s README; often a newer version works on stable (for example, the Rocket web framework needed nightly up to 0.4, and 0.5 runs on stable). Otherwise pick a different crate. See Cargo & crates.
Copied code with #![feature(let_chains)]. Let chains (if let Some(x) = a && x > 0) became stable in Rust 1.88, but only in the 2024 edition. Fix: delete the line (Fix 2) and set edition = "2024" in Cargo.toml. Without that, you get let chains are only allowed in Rust 2024 or later.
Related errors
Section titled “Related errors”- E0658: use of unstable feature: what you usually get after removing the
#![feature]line, if the feature is still nightly-only. - E0599: no method found: if you remove the line and the method really doesn’t exist, or comes from a crate you haven’t added.
- E0463: can’t find crate: if you switch to
criterionordivanand forget to add it toCargo.toml. - E0435: attempt to use a non-constant value in a constant: a common reason people go looking for nightly const features in the first place.
- All compiler errors explained
Quick check
Section titled “Quick check”Quick check
1. You paste code that starts with #![feature(try_blocks)] and get E0554. What does it mean?
2. Under the error, rustc warns that the feature has been stable since 1.88.0. What should you do?
3. You do want nightly for one experiment. What's the cleanest way?
Score: 0 / 3
Read more
Section titled “Read more”- E0554 — Rust error codes index: the official explanation: feature attributes are only allowed on the nightly channel.
- How Rust is Made and “Nightly Rust” — The Rust Book: the stable, beta and nightly channels, and how a feature goes from nightly to stable.
- Channels — The rustup book: installing nightly and using it next to stable.
- The toolchain file — The rustup book: how
rust-toolchain.tomlpicks the compiler for one project, including a pinned nightly date. - The Unstable Book: every feature name you can put in
#![feature], with a link to its tracking issue.