oxc-project/oxc · error · OxcDiagnostic
Unexpected {} in computed function.
Error message
Unexpected {} in computed function. What it means
Diagnostic from oxlint's vue/no-async-in-computed-properties rule (since oxlint 1.71.0), function variant. It fires when a computed passed as a standalone function (not an object property with a key) contains asynchronous constructs: async function, await, Promise construction, .then/.catch/.finally chains, or timed functions. Same hazard as the property variant: async computed functions return Promises Vue cannot track, so the UI never updates with the resolved value.
Source
Thrown at crates/oxc_linter/src/rules/vue/no_async_in_computed_properties.rs:47
impl AsyncKind {
fn as_str(self) -> &'static str {
match self {
Self::AsyncFunction => "async function declaration",
Self::Await => "await operator",
Self::NewPromise => "Promise object",
Self::Asynchronous => "asynchronous action",
Self::Timed => "timed function",
}
}
}
fn unexpected_in_property(span: Span, kind: AsyncKind, key: &str) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("Unexpected {} in \"{}\" computed property.", kind.as_str(), key))
.with_label(span)
}
fn unexpected_in_function(span: Span, kind: AsyncKind) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("Unexpected {} in computed function.", kind.as_str()))
.with_label(span)
}
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
struct NoAsyncInComputedPropertiesConfig {
/// Names of identifiers whose member-call chains (`.then` / `.catch` / `.finally`)
/// should be ignored. Useful for libraries like Zod where `.catch(default)` is
/// a builder API, not a Promise method.
ignored_object_names: FxHashSet<String>,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize, JsonSchema)]
pub struct NoAsyncInComputedProperties(Box<NoAsyncInComputedPropertiesConfig>);
declare_oxc_lint!(
/// ### What it does
///View on GitHub (pinned to e1e7af627c)
Solutions
- Make the computed synchronous; trigger the async fetch from watch/watchEffect/onMounted into a ref
- Return a synchronous placeholder (loading state) computed from reactive flags instead of awaiting inside
- Whitelist builder-API chains via the rule's ignoredObjectNames config when they are not real Promises
Example fix
// before
const fullName = computed(async () => {
const profile = await fetchProfile(user.id)
return `${user.first} ${profile.last}`
})
// after
const profile = ref(null)
watch(() => user.id, async (id) => { profile.value = await fetchProfile(id) }, { immediate: true })
const fullName = computed(() => `${user.first} ${profile.value?.last ?? ''}`) Defensive patterns
Strategy: validation
Validate before calling
# scan function-style computed for async constructs
grep -rnE "computed\((async )?\(" --include='*.vue' --include='*.ts' src
grep -rn "computed" --include='*.vue' src -A8 | grep -E "await |\.then\(|new Promise|setTimeout" Prevention
- Treat any await or .then inside a computed as a design smell and move it to a watcher immediately
- Store async results in refs; derive synchronous views of them in computed
When it happens
Trigger: A computed/getter function expression contains `await x`, `new Promise(...)`, `x.then(...)`, or setTimeout, and is reported via unexpected_in_function with the AsyncKind rendered into the message (e.g., 'Unexpected await operator in computed function.').
Common situations: Getter-style or functional computed wrappers around async APIs; refactoring property computed into arrow-function computed while keeping an await inside; Promise-method false positives from fluent builder libraries, covered by the rule's ignoredObjectNames option.
Related errors
- Unexpected {} in "{}" computed property.
- Change to `throw new TypeError(...)`
- encountered allocation error
- Avoid destructuring from `defineProps`.
- The computed property cannot be used in `data()` because it
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/d653e5b5cd6ea56e.
Report an issue: GitHub.