{"record":{"id":"b5c4e2d01fc78e81","repo":"ruvnet/ruflo","slug":"ruvllmconfig-modelsdir-is-required","errorCode":null,"errorMessage":"RuvllmConfig.modelsDir is required","messagePattern":"RuvllmConfig\\.modelsDir is required","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/appliance/ruvllm-bridge.ts","lineNumber":135,"sourceCode":"    if (LOW.has(w)) score -= 0.1;\n  }\n  return Math.max(0, Math.min(1, score + Math.min(0.2, words.length / 200)));\n}\n\n// ── Bridge ──────────────────────────────────────────────────\n\nexport class RuvllmBridge {\n  private config: Required<RuvllmConfig>;\n  private models: Map<string, ModelInfo> = new Map();\n  private activeModel: string | null = null;\n  private kvCacheEntries = 0;\n  private ruvectorCore: any = null;\n  private ruvectorRouter: any = null;\n  private ruvectorSona: any = null;\n  private ggufEngine: GgufEngineType | null = null;\n\n  constructor(config: RuvllmConfig) {\n    if (!config.modelsDir) throw new Error('RuvllmConfig.modelsDir is required');\n    this.config = { ...DEFAULT_CONFIG, ...config };\n  }\n\n  /** Probe optional @ruvector packages, initialize GGUF engine, and scan modelsDir. */\n  async initialize(): Promise<void> {\n    this.ruvectorCore = await this.tryImport('@ruvector/core');\n    this.ruvectorRouter = await this.tryImport('@ruvector/router');\n    this.ruvectorSona = await this.tryImport('@ruvector/sona');\n\n    // Initialize GGUF engine for local model inference\n    try {\n      const { GgufEngine } = await import('./gguf-engine.js');\n      this.ggufEngine = new GgufEngine({\n        contextSize: this.config.contextSize,\n        maxTokens: this.config.maxTokens,\n        temperature: this.config.temperature,\n        kvCachePath: this.config.kvCachePath,\n        verbose: this.config.verbose,","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/appliance/ruvllm-bridge.ts#L117-L153","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Pass a concrete directory: getRuvllmBridge({ modelsDir: '/path/to/gguf/models' })","If sourced from env, fail fast when unset rather than passing undefined","Default to a stable location such as path.join(os.homedir(), '.claude-flow', 'models') and mkdir it first","Ensure the value is a non-empty string — undefined and '' both throw"],"exampleFix":"// before\nconst bridge = getRuvllmBridge({ modelsDir: process.env.MODELS_DIR }); // undefined → throws\n\n// after\nconst modelsDir = process.env.MODELS_DIR ?? path.join(os.homedir(), '.claude-flow', 'models');\nawait fs.mkdir(modelsDir, { recursive: true });\nconst bridge = getRuvllmBridge({ modelsDir });","handlingStrategy":"validation","validationCode":"import { mkdir } from 'node:fs/promises';\nimport os from 'node:os';\n\nconst modelsDir = process.env.MODELS_DIR ?? `${os.homedir()}/.claude-flow/models`;\nif (typeof modelsDir !== 'string' || modelsDir.length === 0) {\n  throw new Error('Set MODELS_DIR (or pass modelsDir) before starting the appliance');\n}\nawait mkdir(modelsDir, { recursive: true });\nconst bridge = getRuvllmBridge({ modelsDir });","typeGuard":"function isValidRuvllmConfig(c: unknown): c is RuvllmConfig {\n  return (\n    typeof c === 'object' &&\n    c !== null &&\n    typeof (c as RuvllmConfig).modelsDir === 'string' &&\n    (c as RuvllmConfig).modelsDir.length > 0\n  );\n}","tryCatchPattern":null,"preventionTips":["Resolve modelsDir once at boot (env var or explicit path) and pass it to the first getRuvllmBridge call","Add a startup assertion for env-derived config so a missing variable fails before the bridge is constructed","Never pass process.env.X through unvalidated — undefined becomes a constructor throw"],"tags":["ruvllm-bridge","config","validation","required-field"],"backgroundTag":"missing-required-config","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}