nushell/nushell · error
internal error: missing required scope frame
Error message
internal error: missing required scope frame
What it means
StateDelta maintains a stack of ScopeFrames; StateDelta::new() always pushes one frame and enter_scope/exit_scope push and pop it. last_scope_frame_mut() asserts the stack is non-empty before returning the top frame. A panic means the delta's scope stack was emptied — exit_scope was called more often than enter_scope, an engine-state bookkeeping bug rather than a script error.
Source
Thrown at crates/nu-protocol/src/engine/state_delta.rs:87
self.vars.len()
}
pub fn num_decls(&self) -> usize {
self.decls.len()
}
pub fn num_blocks(&self) -> usize {
self.blocks.len()
}
pub fn num_modules(&self) -> usize {
self.modules.len()
}
pub fn last_scope_frame_mut(&mut self) -> &mut ScopeFrame {
self.scope
.last_mut()
.expect("internal error: missing required scope frame")
}
pub fn last_scope_frame(&self) -> &ScopeFrame {
self.scope
.last()
.expect("internal error: missing required scope frame")
}
pub fn last_overlay_mut(&mut self) -> Option<&mut OverlayFrame> {
let last_scope = self
.scope
.last_mut()
.expect("internal error: missing required scope frame");
if let Some(last_overlay_id) = last_scope.active_overlays.last() {
Some(
&mut last_scope
.overlaysView on GitHub (pinned to 8e03210652)
Solutions
- Audit custom code that calls working_set.enter_scope()/exit_scope() and make them strictly balanced (enter once, exit once per path)
- Use the standard parsing/evaluation entry points instead of driving scope frames directly
- Pin the last known-good nu-protocol/nu-parser pair and report the regression upstream with the script that triggers it
Example fix
// before: error path exits a scope it never entered
working_set.exit_scope();
if err { working_set.exit_scope(); return; }
// after: one enter pairs with one exit on every path
working_set.enter_scope();
let result = do_scoped(working_set);
working_set.exit_scope(); Defensive patterns
Strategy: validation
Validate before calling
// StateWorkingSet::delta is accessible in-crate; guard scope stack depth // before engine operations if you drive scopes manually. // (state.delta.scope starts with exactly one frame) assert!(working_set.delta.scope.len() >= 1, "scope stack over-popped");
Prevention
- Pair every enter_scope() with exactly one exit_scope() on all paths, including errors
- Create a fresh StateWorkingSet per parse/eval unit instead of manually unwinding scopes
- Add debug_asserts on scope depth after custom error-handling paths
When it happens
Trigger: An unbalanced enter_scope/exit_scope sequence (parser or engine code path that pops in both success and error branches), followed by any scope lookup: find_decl/find_overlay, variable resolution, merge into permanent state.
Common situations: Patched parsers or embedders driving StateWorkingSet scopes manually; regressions after upgrading nu-protocol/nu-parser; custom repl/eval loops that call exit_scope on error paths that never entered.
Related errors
- internal error: missing required overlay
- internal error: missing overlay
- internal error: could not find source for previously parsed
- internal error: missing variable
- internal error: missing declaration
AI-assisted analysis of nushell/nushell@8e03210652 (2026-08-17).
Data as JSON: /api/errors/e719f2ac52a77e50.
Report an issue: GitHub.