ruvnet/ruflo · critical

Root guidance file not found: ${this.config.rootGuidancePath

Error message

Root guidance file not found: ${this.config.rootGuidancePath}

What it means

GuidanceControlPlane.initialize() step 1 reads the root guidance file (default './CLAUDE.md', overridable via config.rootGuidancePath) through readGuidanceFile, which returns null both when the file is missing and when reading it throws (the catch swallows read errors). A null root content makes initialize() throw this error; the local guidance file ('./CLAUDE.local.md') is optional, only the root file is mandatory. Initialization aborts before compiling any policy bundle.

Source

Thrown at v3/@claude-flow/guidance/src/index.ts:502

  /**
   * Initialize the control plane
   *
   * 1. Read and compile guidance files
   * 2. Load shards into retriever
   * 3. Configure gates
   * 4. Set up headless runner if enabled
   */
  async initialize(): Promise<void> {
    if (this.initialized) return;

    // Step 1: Read guidance files
    const rootContent = await this.readGuidanceFile(this.config.rootGuidancePath);
    const localContent = this.config.localGuidancePath
      ? await this.readGuidanceFile(this.config.localGuidancePath)
      : undefined;

    if (!rootContent) {
      throw new Error(`Root guidance file not found: ${this.config.rootGuidancePath}`);
    }

    // Step 2: Compile
    this.bundle = this.compiler.compile(rootContent, localContent ?? undefined);

    // Step 3: Load into retriever
    await this.retriever.loadBundle(this.bundle);

    // Step 4: Set active rules on gates
    const allRules = [
      ...this.bundle.constitution.rules,
      ...this.bundle.shards.map(s => s.rule),
    ];
    this.gates.setActiveRules(allRules);

    // Step 5: Set up headless runner if enabled
    if (this.config.headlessMode) {
      this.headless = createHeadlessRunner(undefined, this.ledger, this.bundle.constitution.hash);

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Create the guidance file at the path being resolved (default ./CLAUDE.md relative to process.cwd())
  2. Pass an absolute rootGuidancePath in createGuidanceControlPlane config so cwd cannot change resolution
  3. Verify with fs.existsSync AND a readability check (fs.accessSync(path, fs.constants.R_OK)) beforehand, since read errors are swallowed and also surface as 'not found'
  4. Log process.cwd() at startup to catch wrong-working-directory deploys

Example fix

// before
const plane = createGuidanceControlPlane(); // default './CLAUDE.md'
await plane.initialize();
// after
import { existsSync, accessSync, constants } from 'node:fs';
import { resolve } from 'node:path';
const root = resolve(process.cwd(), 'CLAUDE.md'); // or an absolute config path
if (!existsSync(root)) throw new Error(`Missing guidance file: ${root}`);
accessSync(root, constants.R_OK);
const plane = createGuidanceControlPlane({ rootGuidancePath: root });
await plane.initialize();
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync, accessSync, constants } from 'node:fs';
import { resolve } from 'node:path';

const rootPath = resolve(process.cwd(), config.rootGuidancePath ?? './CLAUDE.md');
if (!existsSync(rootPath)) {
  throw new Error(`Guidance file missing at ${rootPath} (cwd: ${process.cwd()})`);
}
accessSync(rootPath, constants.R_OK); // readGuidanceFile swallows read errors as null
await plane.initialize();

Try / catch

try {
  await plane.initialize();
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Root guidance file not found')) {
    // check cwd and ship the guidance file before retrying; do not create an empty file blindly
    throw new Error(`Initialize failed: ${err.message}; running from ${process.cwd()}`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Running in a working directory without CLAUDE.md while keeping the default config; passing a rootGuidancePath that does not exist; a relative path resolved against an unexpected process.cwd() (daemon, container WORKDIR, systemd unit); a file that exists but is unreadable due to permissions.

Common situations: CLI invoked from a subdirectory of the repo; apps packaged without shipping their guidance markdown files; container or service units with a different cwd than local development; permission-restricted mounted volumes.

Related errors


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