ruvnet/ruflo · error · Error

invalid ${label}: ${value}

Error message

invalid ${label}: ${value}

What it means

The worktree coordinator uses assertId() to validate run ids and agent ids against SAFE_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/: lowercase alphanumerics, dots, underscores, hyphens; must start with a letter/digit; max 64 chars. Ids become directory names and registry keys, so anything else (uppercase, slashes, '..', spaces, unicode, empty, >64 chars) is rejected with 'invalid <run id|agent id>: <value>'.

Source

Thrown at v3/@claude-flow/codex/src/worktrees/coordinator.ts:31

export interface WorktreeRunRecord {
  version: 1;
  runId: string;
  repoRoot: string;
  createdAt: number;
  assignments: WorktreeAssignment[];
}

function git(repoRoot: string, args: string[]): string {
  return execFileSync('git', ['-C', repoRoot, ...args], {
    encoding: 'utf8',
    stdio: ['ignore', 'pipe', 'pipe'],
    maxBuffer: 4 * 1024 * 1024,
  }).trim();
}

function assertId(value: string, label: string): void {
  if (!SAFE_ID.test(value)) throw new Error(`invalid ${label}: ${value}`);
}

export class CodexWorktreeCoordinator {
  readonly repoRoot: string;
  readonly registryDir: string;
  readonly worktreeBase: string;

  constructor(repoRoot: string) {
    this.repoRoot = resolve(repoRoot);
    const top = git(this.repoRoot, ['rev-parse', '--show-toplevel']);
    if (resolve(top) !== this.repoRoot) throw new Error(`repoRoot must be the git top-level: ${top}`);
    this.registryDir = join(this.repoRoot, '.claude-flow', 'swarm', 'worktrees');
    this.worktreeBase = join(dirname(this.repoRoot), '.ruflo-worktrees', basename(this.repoRoot));
  }

  prepare(
    runId: string,
    agents: Array<{ id: string; readOnly?: boolean }>,

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Normalize ids before calling: lowercase, replace unsafe chars with '-', trim to 64 chars, ensure it starts with [a-z0-9]
  2. Prefer short slugs like 'agent-1', 'coder-2', 'run-20260818'
  3. Validate in your own code with the same regex so the error surfaces at the source

Example fix

// before
coordinator.prepare('Run #1', [{ id: 'Coder/Alpha' }]); // throws
// after
const SAFE_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/;
const slug = (s: string) => s.toLowerCase().replace(/[^a-z0-9._-]+/g, '-').slice(0, 64);
coordinator.prepare(slug('run-1'), [{ id: slug('coder-alpha') }]);
Defensive patterns

Strategy: type-guard

Validate before calling

const SAFE_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/;
const okId = (s: string) => SAFE_ID.test(s);

Type guard

const SAFE_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/;
function isSafeId(v: unknown): v is string {
  return typeof v === 'string' && SAFE_ID.test(v);
}

Try / catch

try { coordinator.prepare(runId, agents); } catch (e) { if (/^invalid (run|agent) id/.test(String(e))) throw new TypeError(`normalize ids: ${e.message}`); throw e; }

Prevention

When it happens

Trigger: prepare('Run/1', ...) or agent ids like 'Agent Alpha', '../escape', 'Ünicode-id', '', or a 70-char id; ids generated with uuid (uppercase hex) or containing path separators.

Common situations: Callers reuse display names or uuids as agent ids; ids derived from branch names with slashes; usernames with spaces; accidental uppercase from copy-paste.

Related errors


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