ruvnet/ruflo · error
maxOutputBytes must be positive
Error message
maxOutputBytes must be positive
What it means
The DualModeOrchestrator constructor validates config.maxOutputBytes with Number.isFinite(x ?? 1_048_576) && x >= 1. This field caps how much stdout/stderr each spawned worker may produce (default 1 MiB) to bound memory use, so it must be a finite positive number. Unlike maxConcurrent it may be a non-integer float, but zero, negatives, NaN, and Infinity are all rejected.
Source
Thrown at v3/@claude-flow/codex/src/dual-mode/orchestrator.ts:88
totalDuration: number;
errors: string[];
}
/**
* 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,View on GitHub (pinned to fa13ee4ad6)
Solutions
- Set a finite value >= 1, e.g. maxOutputBytes: 2 * 1024 * 1024, or omit it to accept the 1 MiB default.
- Sanitize external input: `const n = Number(raw); if (!Number.isFinite(n) || n < 1) throw new Error('bad maxOutputBytes')`.
- Do not use 0 or Infinity as an 'unlimited' marker — the type has no unlimited mode.
- If workers genuinely emit more than the cap, raise the number rather than special-casing it.
Example fix
// before
new DualModeOrchestrator({ projectPath, maxOutputBytes: Number(env.MAX_OUT) }); // NaN → throws
// after
const cap = Number(env.MAX_OUT);
new DualModeOrchestrator({
projectPath,
maxOutputBytes: Number.isFinite(cap) && cap >= 1 ? cap : 1_048_576,
}); Defensive patterns
Strategy: validation
Validate before calling
function positiveFinite(raw: unknown, fallback = 1_048_576): number {
const n = typeof raw === 'number' ? raw : Number(raw);
return Number.isFinite(n) && n >= 1 ? n : fallback;
}
new DualModeOrchestrator({
projectPath,
maxOutputBytes: positiveFinite(env.MAX_OUTPUT_BYTES), // NaN/0/Infinity → 1 MiB default
}); Try / catch
try {
new DualModeOrchestrator(config);
} catch (err) {
if (err instanceof Error && err.message === 'maxOutputBytes must be positive') {
throw new Error(`maxOutputBytes was ${String(config.maxOutputBytes)} — pass a finite number >= 1 (bytes)`);
}
throw err;
} Prevention
- Do not use 0 or Infinity as an 'unlimited' marker — the field has no unlimited mode
- Sanitize env-var-derived numbers with Number.isFinite before constructing the orchestrator
- Watch subtractive arithmetic (total - overhead) that can go negative for small totals
- Size caps from observed worker output, not guesses
When it happens
Trigger: (1) Setting maxOutputBytes: 0 intending 'no output' (use 1 or redirect instead); (2) NaN from parsing an empty/non-numeric env var or config string; (3) Infinity from Number.MAX_VALUE overflow arithmetic or unbounded 'unlimited' sentinels; (4) negative values from subtractive size math.
Common situations: Sizing output caps from free-form env vars; configs migrated from tools where 0 meant unlimited; arithmetic that computes the cap as size - overhead going negative for tiny buffers.
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
- maxWriters must be a positive integer
- SSRF guard: private/loopback host rejected — ${host}
- JSON.stringify(response.error)
- Failed to create share link
- User not found
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/f79edc17fc230573.
Report an issue: GitHub.