oxc-project/oxc · error · OxcDiagnostic
Either await the Promise or pass a callback function to `nex
Error message
Either await the Promise or pass a callback function to `nextTick`.
What it means
Diagnostic from the oxlint rule `vue/valid-next_tick`. In `check_call`, after ruling out zero args and >1 args, if the single-argument call is ALSO 'awaited' per `is_awaited_promise` (parent is await/return/declarator/assignment/expression-arrow, a `.then` member, or inside `Promise.*` array), the rule reports both-consumed usage. Combining a callback with await (or with `.then`, or with `Promise.all`) is redundant: the callback fires on the same tick resolution AND the promise resolution path also runs, which is confusing and often double-handles the update.
Source
Thrown at crates/oxc_linter/src/rules/vue/valid_next_tick.rs:30
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
///
/// Enforce valid `nextTick` function calls.
///
/// ### Why is this bad?
///
/// `nextTick` is a function that takes either a callback or returns a Promise.
/// Misuse (accessing it as a value, passing extra arguments, both awaiting and
/// passing a callback) is almost always a bug.
///
/// ### ExamplesView on GitHub (pinned to e1e7af627c)
Solutions
- If you migrated to await style, drop the callback: `await nt()`.
- If the callback is essential, remove the await: `nt(callback)`.
- For `.then` chains, remove the callback argument: `nt().then(anotherCallback)`.
Example fix
// before
async mounted() {
await this.$nextTick(callback);
}
// after
async mounted() {
await this.$nextTick();
} Defensive patterns
Strategy: validation
Validate before calling
if (/await\s+(?:this\.\$nextTick|Vue\.nextTick|\bnt)\s*\(\s*\S/.test(src) ||
/(?:this\.\$nextTick|Vue\.nextTick|\bnt)\s*\(\s*\S[^)]*\)\s*\.then/.test(src)) {
console.warn('nextTick used with both a callback and await/.then — pick one');
} Prevention
- Complete callback→Promise migrations: remove leftover callbacks once await is in place.
- One nextTick consumption mechanism per call site.
When it happens
Trigger: `await nt(callback)`, `await Vue.nextTick(callback)`, `await this.$nextTick(callback)`, and `nt(callback).then(anotherCallback)` (the `.then` parent marks the call awaited) inside a component instance method. One argument plus any await-style parent triggers it.
Common situations: Half-finished migrations from callback style to await style that leave the callback in place; defensive coding that both awaits and passes a callback 'to be sure'; chaining `.then` after a callback form.
Related errors
- Await the Promise returned by `nextTick` or pass a callback
- `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/48f7e709326ce534.
Report an issue: GitHub.