hashicorp/consul · error · Error

Unable to locate '${value.class}'

Error message

Unable to locate '${value.class}'

What it means

Thrown during consul-ui boot by the 'container' instance initializer. It reads service registrations from <script data-services> tags embedded in the served HTML and, for every entry whose 'class' is a string, resolves that Ember module id with require.has(). The error means the configured module id (typically an auth-provider class) is not present in the application bundle the browser actually loaded.

Source

Thrown at ui/packages/consul-ui/app/instance-initializers/container.js:29

export const services = assign.all(
  [...doc.querySelectorAll(`script[data-services]`)].map(($item) =>
    JSON.parse($item.dataset[`services`])
  )
);

const inject = function (container, obj) {
  // inject all the things
  Object.entries(obj).forEach(([key, value]) => {
    switch (true) {
      case typeof value.class === 'string':
        if (require.has(value.class)) {
          container.register(
            key.replace('auth-provider:', 'torii-provider:'),
            require(value.class).default
          );
        } else {
          throw new Error(`Unable to locate '${value.class}'`);
        }
        break;
    }
  });
};
export default {
  name: 'container',
  initialize(application) {
    inject(application, services);

    const container = application.lookup('service:container');
    // find all the services and add their classes to the container so we can
    // look instances up by class afterwards as we then resolve the
    // registration for each of these further down this means that any top
    // level code for these services is executed, this is most useful for
    // making sure any annotation type decorators are executed.
    // For now we only want repositories, so only look for those for the moment
    let repositories = container

View on GitHub (pinned to 2397ff0d76)

Solutions

  1. Read the error message for the exact module id, then inspect the <script data-services> payload in the served HTML to see which entry declares it
  2. Verify the module exists in this build: search the dist assets, or run require.has('<module-id>') in the browser console
  3. If the module belongs to an addon, ensure the addon is installed and its module survives the build (not tree-shaken or excluded via resolver config)
  4. Align the backend that emits data-services with the frontend build that ships the module, or correct the typo in the class path
  5. As a last resort remove or replace the entry so application boot can proceed

Example fix

// before: payload references a module id not present in the build
<script type="text/plain" data-services='{"auth-provider:oidc":{"class":"auth-providers/oidc"}}'></script>
// -> Error: Unable to locate 'auth-providers/oidc'

// after: point 'class' at a module id that exists in this build
<script type="text/plain" data-services='{"auth-provider:oidc":{"class":"consul-ui/auth-providers/oidc"}}'></script>
Defensive patterns

Strategy: validation

Validate before calling

// run before app boot, on the same payload the initializer will consume
import require from 'require';

export function unresolvableClasses(services) {
  return Object.entries(services)
    .filter(([, v]) => typeof v?.class === 'string')
    .filter(([, v]) => !require.has(v.class))
    .map(([key, v]) => `${key} -> ${v.class}`);
}
// const missing = unresolvableClasses(services);
// if (missing.length) { console.error('unresolvable service classes', missing); }

Type guard

const isResolvableServiceEntry = (v) =>
  v != null && typeof v.class === 'string' && require.has(v.class);

Try / catch

try {
  await app.boot();
} catch (e) {
  if (e instanceof Error && /Unable to locate/.test(e.message)) {
    // e.message contains the exact missing module id; compare it against
    // the data-services payload to find the misconfigured entry
    reportBootError(e.message, document.querySelectorAll('script[data-services]'));
  }
  throw e;
}

Prevention

When it happens

Trigger: A data-services payload entry like {"class":"some/module-id"} where 'some/module-id' is not resolvable by Ember's require(): module missing from the build (addon not installed or tree-shaken), module renamed/moved after an upgrade, a typo in the configured class path, or HTML generated by a backend that does not match the shipped frontend build.

Common situations: Upgrading consul-ui or its addons where an auth provider module id changed; serving UI assets built separately from the HTML that references them; test/CI harnesses injecting a data-services payload without the corresponding modules; auth-provider config referencing a provider not compiled into the build.


AI-assisted analysis of hashicorp/consul@2397ff0d76 (2026-08-15). Data as JSON: /api/errors/4ee0d28d1650277a. Report an issue: GitHub.