biomejs/biome · error

generated {} helper has unexpected shape

Error message

generated {} helper has unexpected shape

What it means

Biome's xtask codegen validates each generated Promise helper function (the GLOBAL_INSTANCEOF_PROMISE helpers): the helper must be non-async, have no type parameters, bear the expected helper name, take no parameters, and return the predefined GLOBAL_INSTANCEOF_PROMISE_ID type. Any deviation means the generator emitted a helper that downstream type lowering cannot rely on, so the build bails.

Source

Thrown at xtask/codegen/src/generate_global_types/compare.rs:325

        LoweredMemberKind::Named { optional: false }
    };
    if member.kind() != &expected_kind
        || member.type_reference() != &LoweredTypeReference::Predefined(shape.member_type_id)
    {
        bail!(
            "generated Promise.{} member has unexpected shape",
            shape.member_name
        );
    }

    let helper = generated_function(lowered, shape.helper_name, shape.helper_id_constant)?;
    if helper.is_async()
        || !helper.type_parameters().is_empty()
        || helper.name() != Some(shape.helper_name)
        || !helper.parameters().is_empty()
        || helper.return_type() != &LoweredTypeReference::Predefined("GLOBAL_INSTANCEOF_PROMISE_ID")
    {
        bail!(
            "generated {} helper has unexpected shape",
            shape.helper_name
        );
    }
    Ok(())
}

/// Rejects output that differs from the predefined `Array` projection used by the resolver.
fn assert_array_shape(lowered: &LoweredGlobalTypes) -> Result<()> {
    let Some(array) = lowered.global("Array") else {
        bail!("generated globals are missing the Array global");
    };
    if array.id_constant() != "ARRAY_ID_GLOBAL_TYPE_ID" {
        bail!(
            "generated Array global targets {}, expected ARRAY_ID_GLOBAL_TYPE_ID",
            array.id_constant()
        );
    }

View on GitHub (pinned to 3835945f06)

Solutions

  1. Inspect the generated helper for shape.helper_name and restore the expected signature: non-async, no type parameters, no parameters, return type GLOBAL_INSTANCEOF_PROMISE_ID.
  2. Update the expected shape constant (helper_name / helper_id_constant) if the helper intentionally changed, then regenerate.
  3. Re-run `cargo xtask codegen` and review the regenerated global types diff.
Defensive patterns

Strategy: validation

Validate before calling

// Validate generated helper signature before comparing
fn validate_helper(helper: &LoweredFunction, shape: &PromiseShape) -> Result<()> {
  ensure!(!helper.is_async(), "helper {} must not be async", shape.helper_name);
  ensure!(helper.type_parameters().is_empty(), "helper {} must have no type parameters", shape.helper_name);
  ensure!(helper.parameters().is_empty(), "helper {} must take no parameters", shape.helper_name);
  Ok(())
}

Try / catch

if let Err(e) = assert_promise_shape(&lowered, &shape) {
  if e.to_string().contains("unexpected shape") {
    bail!("helper template drifted; regenerate globals: {e}");
  }
  return Err(e);
}

Prevention

When it happens

Trigger: Running `cargo xtask codegen` when generated_function() produced a helper whose signature drifted from the expected shape in assert_promise_method — e.g. a template/codegen change makes the helper async, adds type parameters or parameters, renames it, or alters its return type.

Common situations: Editing the helper-generation template in generate_global_types; renaming the GLOBAL_INSTANCEOF_PROMISE predefined id; a refactor of generated_function changing emission order or signatures.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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