oxc-project/oxc · error · OxcDiagnostic

`nextTick` is a function.

Error message

`nextTick` is a function.

What it means

Diagnostic from the oxlint rule `vue/valid-next-tick` (crates/oxc_linter/src/rules/vue/valid_next_tick.rs). The rule matches three spellings inside Vue component instance methods: an identifier imported from 'vue' (even aliased, e.g. `nextTick as nt`), `Vue.nextTick`, and `this.$nextTick` (or `vm.$nextTick` where `vm` derives from `this`). If the matched reference is used as a value — its parent is not a call callee, not a variable declarator/assignment, and not a conditional — the rule reports '`nextTick` is a function.' and offers an auto-fix that appends `()` after the reference. Referencing the function without calling it does nothing (e.g. `this.$nextTick;` is a no-op statement, `nt.then(cb)` calls `.then` on the function itself).

Source

Thrown at crates/oxc_linter/src/rules/vue/valid_next_tick.rs:17

use oxc_ast::{
    AstKind,
    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;

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Invoke it: `await this.$nextTick()` / `nt()` — or run `oxlint --fix`, which appends the missing `()` automatically.
  2. If you meant to pass the function itself, wrap usage accordingly (`foo.then(nt)` as a call argument is accepted and correct).
  3. For arrays passed to `Promise.all`, call each entry: `Promise.all([nt(), otherPromise])`.

Example fix

// before
async mounted() {
  await this.$nextTick;
  Promise.all([nt, otherPromise]);
}

// after
async mounted() {
  await this.$nextTick();
  Promise.all([nt(), otherPromise]);
}
Defensive patterns

Strategy: validation

Validate before calling

// Flag nextTick used as a value without being called
const re = /(?:this\.\$nextTick|Vue\.nextTick|\bnt\b)(?!\s*\()/g;
for (const m of src.matchAll(re)) {
  const after = src.slice(m.index + m[0].length, m.index + m[0].length + 20);
  if (!/^\s*(?:;|\)|,|=|\.then|$)/.test(after)) continue; // rough context filter
  console.warn(`nextTick referenced without call at offset ${m.index}`);
}

Prevention

When it happens

Trigger: Inside a component instance context (lifecycle hooks like `mounted`, `methods`, or objects passed to `new Vue(...)`, `Vue.extend`, `Vue.mixin`, `defineNuxtComponent`): a bare `this.$nextTick;` statement, `await nt;`, `return this.$nextTick;`, `nt.then(callback)`, or `Promise.all([nt, other])`. Parents that are OK: `foo.then(nt)` (argument position), `let foo = nt`, `foo = nt`, and `bar ? nt : undefined`. The auto-fix inserts `()` at the end of the reference span.

Common situations: Forgetting the parentheses when converting callback style to await style; `Promise.all([this.$nextTick, fetch(...)])` that silently awaits the function object instead of a Promise; refactoring that leaves a stray `this.$nextTick` expression statement.

Related errors


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