oxc-project/oxc · error · OxcDiagnostic
Await the Promise returned by `nextTick` or pass a callback
Error message
Await the Promise returned by `nextTick` or pass a callback function.
What it means
Diagnostic from the oxlint rule `vue/valid-next-tick`. In `check_call`, when a matched `nextTick`/`Vue.nextTick`/`this.$nextTick` call has zero arguments, the rule checks `is_awaited_promise`: the call is 'consumed' if its parent is an await expression, return statement, variable declarator, assignment, an expression-bodied arrow, a `.then` member access, or an element of an array inside a `Promise.*` call. If none apply, the floating call is reported — `nextTick()` returns a Promise, and discarding it means the following code runs before the DOM update flush.
Source
Thrown at crates/oxc_linter/src/rules/vue/valid_next_tick.rs:21
ast::{CallExpression, Expression},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use crate::{
AstNode,
context::LintContext,
rule::Rule,
utils::{is_in_vue_component_instance_method, is_this_object, is_vue_next_tick_import},
};
fn should_be_function_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("`nextTick` is a function.").with_label(span)
}
fn missing_callback_or_await_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Await the Promise returned by `nextTick` or pass a callback function.")
.with_label(span)
}
fn too_many_parameters_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("`nextTick` expects zero or one parameters.").with_label(span)
}
fn either_await_or_callback_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Either await the Promise or pass a callback function to `nextTick`.")
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct ValidNextTick;
declare_oxc_lint!(
/// ### What it does
///View on GitHub (pinned to e1e7af627c)
Solutions
- Await it: make the hook async and write `await nextTick()` before code that depends on the DOM update.
- Or chain it: `nextTick().then(() => { ... })`.
- Or store/return the promise (`const q = nextTick()`) if you intentionally defer handling — the rule accepts those shapes.
- If the call is genuinely fire-and-forget, add `void nextTick()` is NOT in the accepted parent list — restructure to one of the accepted forms instead.
Example fix
// before
async mounted() {
this.$nextTick();
this.doSomethingWithDom();
}
// after
async mounted() {
await this.$nextTick();
this.doSomethingWithDom();
} Defensive patterns
Strategy: validation
Validate before calling
// crude: zero-arg nextTick() call not preceded by await and not followed by .then
const re = /(?<!await\s)(?:this\.\$nextTick|Vue\.nextTick|\bnt)\s*\(\s*\)(?!\s*\.)/g;
if (re.test(src)) console.warn('Floating nextTick() call — its Promise is discarded'); Prevention
- Make the enclosing hook async and await the call whenever later code touches the DOM.
- Prefer the awaited Promise style consistently across the codebase.
When it happens
Trigger: Zero-argument `nt()`, `Vue.nextTick()`, or `this.$nextTick()` inside a component instance method where the result is not consumed — plain expression statement in `mounted()`, or `async mounted() { nt(); ... }` without `await`. Accepted shapes include `await nt()`, `return nt()`, `const q = nt()`, `() => nt()`, `nt().then(cb)`, and `Promise.all([nt(), x])`.
Common situations: Porting `this.$nextTick(callback)` to Promise style and dropping both the callback and the `await`; calling `nextTick()` in non-async hooks where the author assumed it blocks; fire-and-forget calls left after refactors.
Related errors
- Either await the Promise or pass a callback function to `nex
- `nextTick` is a function.
- Change to `throw new TypeError(...)`
- Promise executor functions should not be `async`.
- Unexpected `await` inside a loop.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/39f56f2ce180ea4c.
Report an issue: GitHub.