ruvnet/ruflo · error

AIDefence installed but failed to load

Error message

AIDefence installed but failed to load: ${retryError}.
This usually means npm installed the package somewhere Node's module resolver doesn't search (common with global installs of `claude-flow`). Recovery options:
  1. Run `npm install --save @claude-flow/aidefence` in your project's working directory.
  2. Or run `npx ruflo@latest mcp start` from a directory whose node_modules contains the package.
  3. Or restart the MCP server after the install completes.

What it means

The final failure of the AIDefence loader: auto-install reported success, but both the plain re-import AND the require.resolve + `file://<path>?t=<ts>` cache-bust import still threw. This almost always means npm placed the package somewhere Node's resolver doesn't search relative to the CLI (classic with global installs of claude-flow), so the module exists on disk but is unresolvable. The error embeds the retry error plus three recovery options.

Solutions

  1. Follow option 1: npm install --save @claude-flow/aidefence in your project's working directory, then restart the MCP server.
  2. Option 2: run npx ruflo@latest mcp start from a directory whose node_modules contains the package.
  3. Option 3: simply restart the MCP server after the install completed — the fresh module cache often resolves the newly installed tree.
  4. For global installs, prefer making the package a real project dependency so npm's resolution rules work in your favor.

Example fix

# before
cd ~ && claude-flow mcp start   # global install, aidefence unresolvable -> error 289

# after
cd ~/my-project && npm install --save @claude-flow/aidefence && npx ruflo@latest mcp start
Defensive patterns

Strategy: fallback

Validate before calling

import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
function aidefenceResolvableAfterInstall(): boolean {
  try { require.resolve('@claude-flow/aidefence'); return true; }
  catch {
    console.error('Recovery: cd <project> && npm install --save @claude-flow/aidefence, then restart the MCP server');
    return false;
  }
}

Try / catch

try {
  return await securityScan(text);
} catch (e) {
  if (e instanceof Error && e.message.startsWith('AIDefence installed but failed to load')) {
    notifyOps('aidefence unresolvable from this install layout — restart MCP server from a project dir containing the package');
    return { degraded: true, reason: 'aidefence-module-layout' };
  }
  throw e;
}

Prevention

When it happens

Trigger: Globally installed `claude-flow` auto-installs @claude-flow/aidefence into a prefix (e.g. ~/.npm-global or the npx cache) that is not in the resolution path of the running MCP server; then even the file:// retry fails because require.resolve from the CLI's location can't find it, or the cache-bust import hits a sub-dependency resolution failure.

Common situations: npx/global installs where cwd has no node_modules; running the MCP server from a different directory than where installation happened; ESM resolver quirks with query-string cache busting on some Node versions.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/4bf54e403df677e6. Report an issue: GitHub.

Appendix: source

Thrown at v3/@claude-flow/cli/src/mcp-tools/security-tools.ts:120

      return instance;
    }
  } catch { /* fall through to file:// attempt */ }

  // file:// + cache-bust attempt (covers globally-installed packages whose
  // path the standard resolver missed but require.resolve can locate).
  try {
    const modulePath = require.resolve(packageName);
    const cacheBust = `?t=${Date.now()}`;
    const aidefence = await import(`file://${modulePath}${cacheBust}`);
    const instance = aidefence.createAIDefence({ enableLearning: true });
    if (!instance) {
      throw new Error('createAIDefence returned null after install');
    }
    aidefenceInstance = instance;
    console.error(`[claude-flow] ${packageName} loaded after install (file:// path)`);
    return instance;
  } catch (retryError) {
    throw new Error(
      `AIDefence installed but failed to load: ${retryError}.\n` +
      `This usually means npm installed the package somewhere Node's module resolver doesn't search ` +
      `(common with global installs of \`claude-flow\`). Recovery options:\n` +
      `  1. Run \`npm install --save @claude-flow/aidefence\` in your project's working directory.\n` +
      `  2. Or run \`npx ruflo@latest mcp start\` from a directory whose node_modules contains the package.\n` +
      `  3. Or restart the MCP server after the install completes.`
    );
  }
}

/**
 * Scan input for AI manipulation threats
 */
const aidefenceScanTool: MCPTool = {
  name: 'aidefence_scan',
  description: 'Scan input text for AI manipulation threats (prompt injection, jailbreaks, PII). Returns threat assessment with <10ms latency. Use when nothing native exists — Claude Code does not have a PII / prompt-injection / adversarial-text scanner. Pair with any tool that ingests untrusted input (browser scrape, federation envelope, memory_import_claude).',
  inputSchema: {
    type: 'object',

View on GitHub (pinned to fa13ee4ad6)