emberjs/ember.js · error · Error

Attempted to load a helper, but there wasn't a helper manage

Error message

Attempted to load a helper, but there wasn't a helper manager associated with the definition. The definition was: ${debugToString!(definition)}

What it means

`getInternalHelperManager()` looks up a helper manager for a definition (class, function, or object passed as a helper). If no manager is associated and none is expected to be registered, the library throws in DEBUG builds with the definition rendered via `debugToString`. This catches mis-registered helpers early instead of failing obscurely later at render time.

Source

Thrown at packages/@glimmer/manager/lib/internal/api.ts:165

    () =>
      // eslint-disable-next-line @typescript-eslint/no-base-to-string -- @fixme
      `Attempted to use a value as a helper, but it was not an object or function. Helper definitions must be objects or functions with an associated helper manager. The value was: ${definition}`
  );

  let manager = getManager(HELPER_MANAGERS, definition);

  // Functions are special-cased because functions are defined
  // as the "default" helper, per: https://github.com/emberjs/rfcs/pull/756
  if (manager === undefined && typeof definition === 'function') {
    manager = DEFAULT_MANAGER;
  }

  if (manager) {
    return manager;
  } else if (isOptional === true) {
    return null;
  } else if (DEBUG) {
    throw new Error(
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
      `Attempted to load a helper, but there wasn't a helper manager associated with the definition. The definition was: ${debugToString!(
        definition
      )}`
    );
  }

  return null;
}

export function setInternalComponentManager<T extends object>(
  factory: InternalComponentManager,
  obj: T
): T {
  return setManager(COMPONENT_MANAGERS, factory, obj);
}

export function getInternalComponentManager(definition: object): InternalComponentManager;

View on GitHub (pinned to 26f97246a8)

Solutions

  1. Register the definition with `setHelperManager(managerFactory, definition)` from @glimmer/manager
  2. Verify the value passed is actually the helper definition (not its wrapper or an unrelated class)
  3. Check the printed definition in the error to identify which object lacks a manager
  4. For optional lookups, call `getInternalHelperManager(definition, true)` so null is returned instead of throwing

Example fix

// before
export default class MyHelper {} // no manager registered
// after
import { setHelperManager } from '@glimmer/manager';
class MyHelperManager { ... }
export default setHelperManager(() => new MyHelperManager(), class MyHelper {});
Defensive patterns

Strategy: type-guard

Validate before calling

import { getInternalHelperManager, setHelperManager } from '@glimmer/manager';
if (getInternalHelperManager(definition, true) === null) {
  setHelperManager(() => new MyHelperManager(), definition);
}

Type guard

function hasHelperManager(d: unknown): boolean { return getInternalHelperManager(d, true) !== null; }

Try / catch

try { helper(definition); } catch (e) { if (/wasn't a helper manager/.test(e.message)) throw new Error(`Helper not registered: ${String(definition)}`); throw e; }

Prevention

When it happens

Trigger: Passing a value as a helper that was never registered via `setHelperManager` (or via Ember's helper() decorator/API), e.g. passing a plain function or class where a managed helper definition is required.

Common situations: Migrating between Ember/Glimmer helper APIs where registration was dropped; typos in resolver registration; passing the wrong object (component class instead of helper) into a helper slot.

Related errors


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