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

  1. Make the computed synchronous; trigger the async fetch from watch/watchEffect/onMounted into a ref
  2. Return a synchronous placeholder (loading state) computed from reactive flags instead of awaiting inside
  3. 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

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


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