oxc-project/oxc · warning · OxcDiagnostic

Avoid using non-standard `Promise.{prop_name}` method.

Error message

Avoid using non-standard `Promise.{prop_name}` method.

What it means

Diagnostic from the oxlint rule `promise/spec-only` (plugin `promise`, category `restriction`). It fires on member expressions whose object is exactly the identifier `Promise` and whose static property name is NOT in the built-in PROMISE_STATIC_METHODS allowlist (the standard set: resolve, reject, all, allSettled, any, race, try, withResolvers, ...) and not whitelisted via the `allowedMethods` config option (case-sensitive set). Note it fires on property access alone - `getA(Promise.done)` is flagged even without a call. Non-standard statics tie code to specific libraries (e.g. Bluebird) or polyfills and cost maintenance.

Source

Thrown at crates/oxc_linter/src/rules/promise/spec_only.rs:17

use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_str::CompactStr;
use rustc_hash::FxHashSet;
use schemars::JsonSchema;
use serde::Deserialize;

use crate::{
    AstNode,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
    utils::PROMISE_STATIC_METHODS,
};

fn spec_only(prop_name: &str, member_span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Avoid using non-standard `Promise.{prop_name}` method."))
        .with_label(member_span)
}

#[derive(Debug, Default, Clone, Deserialize)]
pub struct SpecOnly(Box<SpecOnlyConfig>);

#[derive(Debug, Default, Clone, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct SpecOnlyConfig {
    /// List of Promise static methods that are allowed to be used.
    allowed_methods: Option<FxHashSet<CompactStr>>,
}

impl std::ops::Deref for SpecOnly {
    type Target = SpecOnlyConfig;

    fn deref(&self) -> &Self::Target {
        &self.0

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace with a standard equivalent: `Promise.done(p)` becomes `p.catch(err => console.error(err))`
  2. Whitelist intentional extensions: `{ "allowedMethods": ["map", "done"] }` (exact case)
  3. Import the extension library under its own namespace (`Promise = require('bluebird')` locally) instead of relying on the patched global

Example fix

// before
Promise.done(fetchThing())

// after
fetchThing().catch(err => console.error(err))
Defensive patterns

Strategy: validation

Validate before calling

npx oxlint --promise/spec-only src/
# intentional extensions:
#   { "rules": { "promise/spec-only": ["error", { "allowedMethods": ["map", "done"] }] } }

Type guard

// Constrain static access to the spec surface at the type level:
type PromiseStatic =
  | 'resolve' | 'reject' | 'all' | 'allSettled'
  | 'any' | 'race' | 'try' | 'withResolvers';
const isSpecStatic = (name: string): name is PromiseStatic =>
  ['resolve', 'reject', 'all', 'allSettled', 'any', 'race', 'try', 'withResolvers'].includes(name);

Prevention

When it happens

Trigger: `Promise.done()`; `Promise.map(items, fn)` (Bluebird); `Promise.promisify(fn)`; any `Promise.<unknown>()` access; a method listed in `allowedMethods` with different casing (matching is case-sensitive per the tests).

Common situations: Bluebird-era codebases; legacy `Promise.done` used as terminal catch; polyfills adding statics to the global; enabling the `restriction` category during an oxlint adoption.

Related errors


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