oxc-project/oxc · warning
Cannot create a `NonEmptyStack` from an empty iterator
Error message
Cannot create a `NonEmptyStack` from an empty iterator
What it means
Diagnostic from oxlint's vue/require-render-return rule (crates/oxc_linter/src/rules/vue/require_render_return.rs). A `render` function on a Vue component options object must return a value on every code path — Vue invokes it to produce the VNode tree, and a falling-through path yields `undefined`, rendering nothing. The rule runs control-flow analysis (definitely_returns_in_all_codepaths) over the render body.
Source
Thrown at crates/oxc_data_structures/src/stack/non_empty.rs:564
/// No allocation occurs, and no data is copied.
#[inline]
fn from(stack: NonEmptyStack<T>) -> Self {
stack.into_vec()
}
}
impl<T> FromIterator<T> for NonEmptyStack<T> {
/// Create a [`NonEmptyStack`] from an iterator.
///
/// # Panics
/// Panics if the iterator is empty.
#[inline] // It mostly just delegates to `Vec::from_iter`
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
// Collect into a `Vec` first, because `Vec` has specialized implementations of `from_iter`
// for various kinds of iterators, which we cannot replicate in stable Rust
let vec = Vec::from_iter(iter);
Self::try_from(vec)
.unwrap_or_else(|_| panic!("Cannot create a `NonEmptyStack` from an empty iterator"))
}
}
// SAFETY: `NonEmptyStack<T>` can be `Send` / `Sync` if `T` is `Send` / `Sync`.
// It does not use interior mutability, and is essentially the same as `Vec<T>` in this respect,
// which implements `Send` / `Sync` in the same way.
unsafe impl<T: Send> Send for NonEmptyStack<T> {}
// SAFETY: See above.
unsafe impl<T: Sync> Sync for NonEmptyStack<T> {}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! assert_len_cap_last {
($stack:ident, $len:expr, $capacity:expr, $last:expr) => {
assert_eq!($stack.len(), $len);
assert_eq!($stack.capacity(), $capacity);View on GitHub (pinned to 36ec0ef2ba)
Solutions
- Add a fallback `return h('div')` (or another VNode) after the conditionals so every path returns.
- Return `null` for intentionally empty states — still a value, and Vue renders a placeholder.
- Restructure to a single return: `return this.show ? h('div', this.msg) : h('span')`.
Example fix
// before
render() {
if (this.show) return h('div', this.msg);
}
// after
render() {
if (this.show) return h('div', this.msg);
return h('div');
} Defensive patterns
Strategy: validation
Validate before calling
// warn when a render function body has no return statement
const fn = source.slice(source.indexOf('render('));
const body = fn.slice(0, fn.indexOf('}'));
if (body && !/\breturn\b/.test(body)) {
throw new Error('render() must return a VNode on every path');
} Prevention
- End every render function with an unconditional return.
- Prefer templates or single-expression h()/JSX arrow bodies.
- Cover render branches with snapshot tests — an empty render is caught immediately.
When it happens
Trigger: A `render()` method (or `render: function` / arrow form) on a Vue component options object where some branch lacks a return, e.g. `render(h) { if (this.x) return h('div'); }` — the implicit else path returns undefined. Returns inside callbacks (forEach, map callbacks) do not count as returns of the render function itself.
Common situations: Hand-written render functions and JSX components; early returns added during debugging then forgotten; refactors that move the return into a nested callback.
Related errors
- capacity overflow
- Invalid fix capabilities. Did you mean 'fix'?
- Invalid fix capabilities. Did you mean 'suggestion'?
- Change to `throw new TypeError(...)`
- Could not find the reuseWorker option in ${path}
AI-assisted analysis of oxc-project/oxc@36ec0ef2ba (2026-08-20).
Data as JSON: /api/errors/6532284cf2c12e7a.
Report an issue: GitHub.