emberjs/ember.js · error · Error

The `hasScheduledEffect` capability has not yet been impleme

Error message

The `hasScheduledEffect` capability has not yet been implemented for helper managers. Please pass `hasValue` instead

What it means

Although `hasScheduledEffect` is an accepted capability name for helper managers, it is not implemented yet. `helperCapabilities()` throws immediately when it is passed in DEBUG builds, directing authors to the `hasValue` capability instead. This is a forward-compatibility guard for a future feature.

Source

Thrown at packages/@glimmer/manager/lib/public/helper.ts:47

): HelperCapabilities {
  debugAssert(
    managerAPI === '3.23',
    () =>
      `Invalid helper manager compatibility specified; you specified ${managerAPI}, but only '3.23' is supported.`
  );

  if (
    DEBUG &&
    (!(options.hasValue || options.hasScheduledEffect) ||
      (options.hasValue && options.hasScheduledEffect))
  ) {
    throw new Error(
      'You must pass either the `hasValue` OR the `hasScheduledEffect` capability when defining a helper manager. Passing neither, or both, is not permitted.'
    );
  }

  if (DEBUG && options.hasScheduledEffect) {
    throw new Error(
      'The `hasScheduledEffect` capability has not yet been implemented for helper managers. Please pass `hasValue` instead'
    );
  }

  return buildCapabilities({
    hasValue: Boolean(options.hasValue),
    hasDestroyable: Boolean(options.hasDestroyable),
    hasScheduledEffect: Boolean(options.hasScheduledEffect),
  });
}

////////////

export function hasValue(
  manager: HelperManager<unknown>
): manager is HelperManagerWithValue<unknown> {
  return manager.capabilities.hasValue;
}

View on GitHub (pinned to 26f97246a8)

Solutions

  1. Replace `hasScheduledEffect: true` with `hasValue: true` and implement `compute()` returning a value
  2. Restructure the helper so its effect is expressed through the returned value (e.g. reactive values from @glimmer/validator)
  3. Track Glimmer releases for when hasScheduledEffect is implemented before using it
  4. Remove stale capability options copied from design proposals

Example fix

// before
capabilities = helperCapabilities('3.23', { hasScheduledEffect: true });
// after
capabilities = helperCapabilities('3.23', { hasValue: true });
Defensive patterns

Strategy: validation

Validate before calling

function buildHelperCaps(opts: { hasValue?: boolean; hasScheduledEffect?: boolean }) {
  if (opts.hasScheduledEffect) throw new Error('hasScheduledEffect is not implemented; use hasValue');
  return helperCapabilities('3.23', { hasValue: true });
}

Type guard

const isSupportedHelperCaps = (o: { hasValue?: boolean; hasScheduledEffect?: boolean }): boolean => !o.hasScheduledEffect && !!o.hasValue;

Try / catch

try { caps = helperCapabilities('3.23', opts); } catch (e) { if (/hasScheduledEffect` capability has not yet been implemented/.test(e.message)) caps = helperCapabilities('3.23', { hasValue: true }); else throw e; }

Prevention

When it happens

Trigger: Passing `{ hasScheduledEffect: true }` to `helperCapabilities('3.23', ...)` while defining a helper manager, usually copied from design docs or issues describing the planned API.

Common situations: Following RFC/design documentation before implementation; attempting to build reactive/effect-style helpers; migrating custom helpers from other frameworks that support effects.

Related errors


AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01). Data as JSON: /api/errors/367199484b6b02ed. Report an issue: GitHub.