ruvnet/ruflo · error
maxWriters must be a positive integer
Error message
maxWriters must be a positive integer
What it means
The DualModeOrchestrator constructor validates config.maxWriters with Number.isInteger(x ?? 2) && x >= 1. maxWriters bounds how many workers may hold git-writing capability simultaneously (worktree isolation aside, the orchestrator refuses configurations that would let more than this many writers run at once), so it must be a positive integer — 0, negatives, floats, and NaN are rejected.
Source
Thrown at v3/@claude-flow/codex/src/dual-mode/orchestrator.ts:91
/**
* Orchestrates parallel execution of Claude Code and Codex workers
*/
export class DualModeOrchestrator extends EventEmitter {
private config: Required<DualModeConfig>;
private workers: Map<string, WorkerResult> = new Map();
private processes: Map<string, ChildProcess> = new Map();
constructor(config: DualModeConfig) {
super();
if (!Number.isInteger(config.maxConcurrent ?? 4) || (config.maxConcurrent ?? 4) < 1) {
throw new Error('maxConcurrent must be a positive integer');
}
if (!Number.isFinite(config.maxOutputBytes ?? 1_048_576) || (config.maxOutputBytes ?? 1_048_576) < 1) {
throw new Error('maxOutputBytes must be positive');
}
if (!Number.isInteger(config.maxWriters ?? 2) || (config.maxWriters ?? 2) < 1) {
throw new Error('maxWriters must be a positive integer');
}
this.config = {
projectPath: config.projectPath,
memoryDbPath: path.resolve(
config.memoryDbPath
?? process.env.CLAUDE_FLOW_DB_PATH
?? path.join(config.projectPath, '.claude-flow', 'dual-mode-memory.db'),
),
maxConcurrent: config.maxConcurrent ?? 4,
sharedNamespace: config.sharedNamespace ?? 'collaboration',
timeout: config.timeout ?? 300000, // 5 minutes
claudeCommand: config.claudeCommand ?? 'claude',
codexCommand: config.codexCommand ?? 'codex',
maxOutputBytes: config.maxOutputBytes ?? 1_048_576,
maxWriters: config.maxWriters ?? 2,
worktreeIsolation: config.worktreeIsolation ?? false,
dependencyFailure: config.dependencyFailure ?? 'cancel',
policyPreflight: config.policyPreflight ?? false,View on GitHub (pinned to fa13ee4ad6)
Solutions
- Pass a positive integer (e.g. maxWriters: 2) or omit it to accept the default of 2.
- For read-only pipelines, mark workers appropriately / give them no writing role — do not zero this field.
- Validate external input before construction: `Number.isInteger(n) && n >= 1` else throw with your own clearer message.
- Keep maxWriters <= maxConcurrent; a writers cap above total concurrency is meaningless and usually signals a config mistake.
Example fix
// before
new DualModeOrchestrator({ projectPath, maxWriters: Number(cfg.max_writers) }); // '' → NaN → throws
// after
const w = Number(cfg.max_writers);
new DualModeOrchestrator({ projectPath, maxWriters: Number.isInteger(w) && w >= 1 ? w : 2 }); Defensive patterns
Strategy: validation
Validate before calling
const raw = cfg.max_writers;
const maxWriters = Number.isInteger(Number(raw)) && Number(raw) >= 1 ? Number(raw) : 2;
if (maxWriters > maxConcurrent) {
// meaningless cap — tighten it instead of shipping a config smell
maxWritersAdjusted = maxConcurrent;
}
new DualModeOrchestrator({ projectPath, maxConcurrent, maxWriters }); Try / catch
try {
new DualModeOrchestrator(config);
} catch (err) {
if (err instanceof Error && err.message === 'maxWriters must be a positive integer') {
new DualModeOrchestrator({ ...config, maxWriters: 2 }); // fall back to the default cap
} else throw err;
} Prevention
- Validate integer >= 1 for any writer-cap sourced from env/TOML/JSON before construction
- Zero is not 'read-only mode' — structure read-only pipelines by worker role instead
- Keep maxWriters <= maxConcurrent so the cap is meaningful
- Document the cap when sharing configs; other teams inherit it verbatim
When it happens
Trigger: (1) maxWriters: 0 in a misguided attempt to make the run read-only; (2) NaN from unvalidated env/config strings; (3) fractional values like 1.5 from dividing a worker count; (4) negative numbers from arithmetic on template parameters.
Common situations: Derived configs that compute maxWriters = workers.length / branches and round wrongly; security-minded users zeroing the field instead of structuring read-only workers; string-typed values in JSON/TOML configs.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- maxOutputBytes must be positive
- writer ${worker.id} requires an isolated worktree
- concurrent writers must use distinct worktrees: ${writerPath
- SSRF guard: private/loopback host rejected — ${host}
- JSON.stringify(response.error)
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/5cca626f09f03747.
Report an issue: GitHub.