jackwener/OpenCLI · error · CliError

ADAPTER_LOAD

ADAPTER_LOAD

Error message

Failed to load adapter module ${modulePath}: ${getErrorMessage(err)}

What it means

runCommand dynamically imports an adapter module via import(importUrl); when the import rejects (file missing, unreadable, or containing a syntax/runtime error at load time), it discards the cached load promise and throws adapterLoadError with code ADAPTER_LOAD, wrapping the underlying error message plus a hint to check the file exists and parses.

Source

Thrown at src/execution.ts:131

      try {
        const stat = fs.statSync(modulePath);
        const prevMtime = _moduleMtimes.get(modulePath);
        if (prevMtime !== undefined && stat.mtimeMs !== prevMtime) {
          _loadedModules.delete(modulePath);
          _moduleMtimes.delete(modulePath);
        }
      } catch { /* file may have been deleted; let import below handle it */ }
    }
    if (!_loadedModules.has(modulePath)) {
      const url = pathToFileURL(modulePath).href;
      const importUrl = _moduleMtimes.has(modulePath) ? `${url}?t=${Date.now()}` : url;
      const loadPromise = import(importUrl).then(
        () => {
          try { _moduleMtimes.set(modulePath, fs.statSync(modulePath).mtimeMs); } catch {}
        },
        (err) => {
          _loadedModules.delete(modulePath);
          throw adapterLoadError(
            `Failed to load adapter module ${modulePath}: ${getErrorMessage(err)}`,
            'Check that the adapter file exists and has no syntax errors.',
          );
        },
      );
      _loadedModules.set(modulePath, loadPromise);
    }
    await _loadedModules.get(modulePath);

    const updated = getRegistry().get(fullName(cmd));
    if (updated?.func) {
      return runCommandFunc(updated, page, kwargs, debug);
    }
    if (updated?.pipeline) return executePipeline(page, updated.pipeline, { args: kwargs, debug });
  }

  if (cmd.func) return runCommandFunc(cmd, page, kwargs, debug);
  if (cmd.pipeline) return executePipeline(page, cmd.pipeline, { args: kwargs, debug });

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the wrapped message after 'Failed to load adapter module' to see the underlying import error (ENOENT vs syntax vs missing dep).
  2. Verify the adapter file exists at modulePath and the path in your task config is correct.
  3. Run the adapter through node --check (or your typecheck/lint) to find syntax errors.
  4. Install missing dependencies referenced by the adapter (npm install) and confirm Node version compatibility.
  5. Fix the error and rerun — note runCommand clears the cached failed promise so the retry performs a fresh import.

Example fix

// before (task config points at wrong path)
"adapter": "./adapters/scrape.jss"
// after
"adapter": "./adapters/scrape.js"
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs';
import path from 'node:path';
if (!fs.existsSync(adapterPath)) throw new Error(`Adapter not found: ${adapterPath}`);
try { new (require('node:vm').Script)(fs.readFileSync(adapterPath, 'utf8')); }
catch (e) { throw new Error(`Adapter has a syntax error: ${e.message}`); }

Try / catch

try {
  await runTask(task);
} catch (e) {
  if (e.code === 'ADAPTER_LOAD') {
    console.error(`Fix adapter at the path in the message: ${e.message}\n${e.hint ?? ''}`);
    process.exitCode = 1;
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: A task/command whose adapter modulePath fails import: nonexistent or renamed adapter file, permission errors, a syntax error in the adapter, or a broken transitive dependency imported by the adapter.

Common situations: Typos in adapter paths in task config, adapters referencing modules not installed in the current project, Node version lacking needed syntax, or a partially edited adapter saved with errors.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/1596de2fc201f846. Report an issue: GitHub.