biomejs/biome · error

{} must be a method

Error message

{} must be a method

What it means

reject_selected_promise_non_method aborts when a property or accessor in a Promise declaration has the same name as one of the required PROMISE_METHOD_SPECIFICATIONS entries at the same member location (instance or static). Required methods must be declared as methods, not as arrow-function-typed properties or get accessors, so the strict shape check fails.

Source

Thrown at xtask/codegen/src/generate_global_types/lower.rs:1042

        return Ok(None);
    };
    let name = name.name()?;
    Ok(PROMISE_METHOD_SPECIFICATIONS
        .iter()
        .copied()
        .enumerate()
        .find(|(_, specification)| {
            specification.location == location && specification.source_name == name.text()
        }))
}

/// Rejects properties and accessors only when their names belong to the selected projection.
fn reject_selected_promise_non_method(
    name: AnyJsObjectMemberName,
    location: PromiseMemberLocation,
) -> Result<()> {
    if let Some((_, specification)) = selected_promise_method(name, location)? {
        bail!("{} must be a method", specification.global_name);
    }
    Ok(())
}

/// Requires the global value declaration to retain its constructor interface.
fn validate_promise_constructor_reference(
    records: &[DeclarationRecord],
    source_cache: &mut ParsedSourceCache,
) -> Result<()> {
    let mut saw_value = false;
    for record in records {
        let DeclarationKind::VariableDeclarator { .. } = &record.kind else {
            continue;
        };
        let declarator = source_cache
            .find_variable_declarator(record)?
            .with_context(|| {
                format!(

View on GitHub (pinned to 3835945f06)

Solutions

  1. Convert the property or accessor into a method signature in the lib sources (e.g. `then<R1, R2>(...): Promise<...>;`)
  2. Rename the conflicting member if it is not meant to satisfy the specification
  3. Allow property-style methods in lower.rs if the new shape is intentional

Example fix

// before
interface Promise<T> { then: <R1, R2>(...: ...) => Promise<R1 | R2>; }
// after
interface Promise<T> { then<R1, R2>(onfulfilled: ..., onrejected: ...): Promise<R1 | R2>; }
Defensive patterns

Strategy: validation

Validate before calling

for (const m of promiseDecl.members) {
  if (REQUIRED_METHODS.includes(m.name) && (m.type === "Property" || m.type === "Accessor")) {
    throw new Error(`'${m.name}' must be a method signature, not a property/accessor`);
  }
}

Prevention

When it happens

Trigger: Running generate_global_types when lib sources declare e.g. `then: (onfulfilled: ...) => ...` (property with function type), `get then() {...}`, or a static property named resolve/all instead of a method signature.

Common situations: Lib snapshots rewritten to property-style declarations; codemods converting method signatures to function-typed properties; vendor type definitions using accessor style.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of biomejs/biome@3835945f06 (2026-09-13). Data as JSON: /api/errors/fad6692d3088732d. Report an issue: GitHub.