ruvnet/ruflo · error · Error

unknown game " ". Known

Error message

unknown game "${key}". Known: ${Object.keys(GAMES).join(', ')}

What it means

The config MCP tools (config_get / config_save) run every user-supplied path through validateConfigPath(), a security hardening step that refuses any path whose normalized form starts with '/' or '\'. The tool only accepts config paths relative to the MCP server's process.cwd(), preventing an MCP client from reading or writing arbitrary host files. Even a perfectly valid absolute path like /home/me/proj/claude-flow.config.json is rejected before any other check runs.

Solutions

  1. Pass a relative path rooted at the MCP server's working directory, e.g. "./claude-flow.config.json" or "config/prod.config.json"
  2. If you hold an absolute path, convert it first: path.relative(process.cwd(), absPath) and pass the result (keep it free of '..' segments)
  3. Start the MCP server with its working directory set to the project root so the default './claude-flow.config.json' resolves correctly
  4. If absolute paths are a hard requirement, modify validateConfigPath to accept an explicit allowlisted base directory instead of relying on cwd

Example fix

// before
await client.callTool('config_save', {
  path: path.resolve('./config/claude-flow.config.json'), // -> /abs/... throws [1120]
  config: cfg,
});

// after
await client.callTool('config_save', {
  path: 'config/claude-flow.config.json', // relative to server cwd
  config: cfg,
});
Defensive patterns

Strategy: validation

Validate before calling

import { isAbsolute, relative, normalize } from 'path';

function toSafeConfigPath(raw: string): string | null {
  const rel = isAbsolute(raw) ? relative(process.cwd(), raw) : normalize(raw);
  if (isAbsolute(rel) || rel.startsWith('..')) return null; // cannot be expressed safely
  return rel.split(/[\\/]/).includes('..') ? null : rel;
}

Try / catch

try {
  await client.callTool('config_save', { path, config });
} catch (e) {
  if (e instanceof Error && e.message.includes('Absolute paths are not allowed')) {
    path = toSafeConfigPath(path) ?? './claude-flow.config.json';
    await client.callTool('config_save', { path, config });
  } else throw e;
}

Prevention

When it happens

Trigger: Calling config_save or config_load with path="/home/user/project/claude-flow.config.json"; passing a Windows drive-absolute path such as "C:\projects\config.json" (its normalize()d form still starts with the drive, but UNC paths \\server\share\c.json start with '\' and hit this branch); a client wrapper that does path.resolve() or path.join(rootDir, ...) before sending the tool call.

Common situations: Scripts ported from the claude-flow CLI (which accepts absolute config paths) to the MCP tool API; CI pipelines that build absolute paths from $PWD or $HOME; MCP clients that 'helpfully' canonicalize relative paths to absolute before invoking the tool.

Related errors


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

Appendix: source

Thrown at plugins/ruflo-arena/src/domain/games.ts:59

  {
    '0|0': [1, -1],
    '1|1': [1, -1],
    '0|1': [-1, 1],
    '1|0': [-1, 1],
  },
  true,
);

export const GAMES: Record<string, GameSpec> = {
  'prisoners-dilemma': prisonersDilemma,
  pd: prisonersDilemma,
  'match-or-not': matchOrNot,
  mon: matchOrNot,
};

export function getGame(key: string): GameSpec {
  const g = GAMES[key];
  if (!g) throw new Error(`unknown game "${key}". Known: ${Object.keys(GAMES).join(', ')}`);
  return g;
}

View on GitHub (pinned to fa13ee4ad6)