ajaxorg/ace · error · Error

couldn't load module " + theme + " or it didn't call define

Error message

couldn't load module " + theme + " or it didn't call define

What it means

VirtualRenderer throws this Error when the theme module loaded asynchronously either failed to load or loaded without defining the expected API (a cssClass property). After $theme.loadModule resolves via afterLoad, a falsy module or a module missing cssClass means the theme script never registered itself (e.g., never called define).

Source

Thrown at src/virtual_renderer.js:2043

        this.$themeId = theme;
        _self._dispatchEvent('themeChange',{theme:theme});

        if (!theme || typeof theme == "string") {
            // @ts-ignore
            var moduleName = theme || this.$options.theme.initialValue;
            config.loadModule(["theme", moduleName], afterLoad);
        } else {
            afterLoad(theme);
        }

        /**
         * @param {Theme} module
         */
        function afterLoad(module) {
            if (_self.$themeId != theme)
                return cb && cb();
            if (!module || !module.cssClass)
                throw new Error("couldn't load module " + theme + " or it didn't call define");
            if (module.$id)
                _self.$themeId = module.$id;
            dom.importCssString(
                module.cssText,
                module.cssClass,
                _self.container
            );
            if (_self.theme)
                dom.removeCssClass(_self.container, _self.theme.cssClass);
            /**@type {any}*/
            var padding = "padding" in module ? module.padding
                : "padding" in (_self.theme || {}) ? 4 : _self.$padding;
            if (_self.$padding && padding != _self.$padding)
                _self.setPadding(padding);

            if (_self.$gutterLayer) {
                var showGutterCursor = module["$showGutterCursorMarker"];
                if (showGutterCursor && !_self.$gutterLayer.$showCursorMarker) {

View on GitHub (pinned to 2c1eddc392)

Solutions

  1. Verify the theme name/path exists, e.g. ace/theme/twilight — check the lib/ace/theme directory or CDN
  2. Check the browser network/console for 404s or CSP blocks on the theme script
  3. If self-hosting, configure the loader/basePath so 'ace/theme/x' resolves to the real theme file
  4. Ensure the theme module is included in your bundle or set the theme to a known-good built-in like 'ace/theme/textmate'

Example fix

// before
editor.setTheme('ace/theme/monokai_dark'); // doesn't exist
// after
editor.setTheme('ace/theme/monokai');
Defensive patterns

Strategy: fallback

Validate before calling

var themeName = 'ace/theme/monokai';
if (!/^ace\/theme\/[\w-]+$/.test(themeName)) throw new Error('bad theme name');
// verify availability if using ace's config: ace.config.loadModule(themeName, function(m){ if(!m) fallback(); });

Type guard

function isLoadedTheme(m) { return m && typeof m === 'object' && typeof m.cssClass === 'string' && m.cssClass.length > 0; }

Try / catch

try {
  renderer.setTheme('ace/theme/mytheme');
} catch (e) {
  if (/couldn't load module/.test(e.message)) renderer.setTheme('ace/theme/textmate');
  else throw e;
}

Prevention

When it happens

Trigger: renderer.setTheme('ace/theme/Name') where the theme file does not exist at the resolved path, the CDN/network request fails, or the theme script is an old/incorrect build that doesn't call define() to export {cssClass, cssText}.

Common situations: Typo in theme name ('solarized_dark' vs 'solarized_dark'), self-hosting ace files with a broken path mapping for ace/theme/*, ad blockers or CSP blocking the theme script, or bundling ace without its theme modules.


AI-assisted analysis of ajaxorg/ace@2c1eddc392 (2026-08-30). Data as JSON: /api/errors/de9b43307dc9a146. Report an issue: GitHub.