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

  1. Await it: make the hook async and write `await nextTick()` before code that depends on the DOM update.
  2. Or chain it: `nextTick().then(() => { ... })`.
  3. Or store/return the promise (`const q = nextTick()`) if you intentionally defer handling — the rule accepts those shapes.
  4. 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

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


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/39f56f2ce180ea4c. Report an issue: GitHub.