ruvnet/ruflo · error

RuvllmConfig.modelsDir is required

Error message

RuvllmConfig.modelsDir is required

What it means

RuvllmBridge's constructor validates that config.modelsDir is truthy before merging with DEFAULT_CONFIG (whose defaults do not include modelsDir), throwing immediately on `new RuvllmBridge(config)` or the first `getRuvllmBridge(config)`. It is a fail-fast guard so an unconfigured bridge never reaches the model-directory scan with no directory to scan.

Solutions

  1. Pass a concrete directory: getRuvllmBridge({ modelsDir: '/path/to/gguf/models' })
  2. If sourced from env, fail fast when unset rather than passing undefined
  3. Default to a stable location such as path.join(os.homedir(), '.claude-flow', 'models') and mkdir it first
  4. Ensure the value is a non-empty string — undefined and '' both throw

Example fix

// before
const bridge = getRuvllmBridge({ modelsDir: process.env.MODELS_DIR }); // undefined → throws

// after
const modelsDir = process.env.MODELS_DIR ?? path.join(os.homedir(), '.claude-flow', 'models');
await fs.mkdir(modelsDir, { recursive: true });
const bridge = getRuvllmBridge({ modelsDir });
Defensive patterns

Strategy: validation

Validate before calling

import { mkdir } from 'node:fs/promises';
import os from 'node:os';

const modelsDir = process.env.MODELS_DIR ?? `${os.homedir()}/.claude-flow/models`;
if (typeof modelsDir !== 'string' || modelsDir.length === 0) {
  throw new Error('Set MODELS_DIR (or pass modelsDir) before starting the appliance');
}
await mkdir(modelsDir, { recursive: true });
const bridge = getRuvllmBridge({ modelsDir });

Type guard

function isValidRuvllmConfig(c: unknown): c is RuvllmConfig {
  return (
    typeof c === 'object' &&
    c !== null &&
    typeof (c as RuvllmConfig).modelsDir === 'string' &&
    (c as RuvllmConfig).modelsDir.length > 0
  );
}

Prevention

When it happens

Trigger: `new RuvllmBridge({})`; `getRuvllmBridge()` with no prior configured call; passing `modelsDir: process.env.MODELS_DIR` when MODELS_DIR is undefined; passing an empty string as modelsDir.

Common situations: Building the bridge before application config loads; env var name typo (MODELS_DIR vs MODELSDIR); CI where the variable is not exported; tests constructing the bridge without a fixture directory.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at v3/@claude-flow/cli/src/appliance/ruvllm-bridge.ts:135

    if (LOW.has(w)) score -= 0.1;
  }
  return Math.max(0, Math.min(1, score + Math.min(0.2, words.length / 200)));
}

// ── Bridge ──────────────────────────────────────────────────

export class RuvllmBridge {
  private config: Required<RuvllmConfig>;
  private models: Map<string, ModelInfo> = new Map();
  private activeModel: string | null = null;
  private kvCacheEntries = 0;
  private ruvectorCore: any = null;
  private ruvectorRouter: any = null;
  private ruvectorSona: any = null;
  private ggufEngine: GgufEngineType | null = null;

  constructor(config: RuvllmConfig) {
    if (!config.modelsDir) throw new Error('RuvllmConfig.modelsDir is required');
    this.config = { ...DEFAULT_CONFIG, ...config };
  }

  /** Probe optional @ruvector packages, initialize GGUF engine, and scan modelsDir. */
  async initialize(): Promise<void> {
    this.ruvectorCore = await this.tryImport('@ruvector/core');
    this.ruvectorRouter = await this.tryImport('@ruvector/router');
    this.ruvectorSona = await this.tryImport('@ruvector/sona');

    // Initialize GGUF engine for local model inference
    try {
      const { GgufEngine } = await import('./gguf-engine.js');
      this.ggufEngine = new GgufEngine({
        contextSize: this.config.contextSize,
        maxTokens: this.config.maxTokens,
        temperature: this.config.temperature,
        kvCachePath: this.config.kvCachePath,
        verbose: this.config.verbose,

View on GitHub (pinned to fa13ee4ad6)