ruvnet/ruflo · error

Event log path contains null bytes

Error message

Event log path contains null bytes

What it means

validatePath() rejects any event-log path containing a NUL byte before it reaches Node's fs APIs. Paths with embedded NULs are invalid on Linux/macOS (ERR_INVALID_ARG_VALUE) and are also a classic path-injection vector, so RvfEventLog construction/initialization fails fast with this message. The offending value almost always originates from user input, config files, or environment variables.

Source

Thrown at v3/@claude-flow/shared/src/events/rvf-event-log.ts:28

 *   Record:       4 bytes (uint32 BE payload length) + N bytes (JSON payload)
 *
 * In-memory indexes are rebuilt on initialize() by replaying the file.
 * Snapshots are stored in a separate `.snap.rvf` file using the same format.
 *
 * @module v3/shared/events/rvf-event-log
 */

import { EventEmitter } from 'node:events';
import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, renameSync } from 'node:fs';
import { dirname } from 'node:path';
import type { DomainEvent } from './domain-events.js';

// Re-export shared interfaces so consumers do not need to import event-store.ts
import type { EventFilter, EventSnapshot, EventStoreStats } from './event-store.js';

/** Validate a file path is safe */
function validatePath(p: string): void {
  if (p.includes('\0')) throw new Error('Event log path contains null bytes');
}

// =============================================================================
// Configuration
// =============================================================================

export interface RvfEventLogConfig {
  /** Path to event log file */
  logPath: string;
  /** Enable verbose logging */
  verbose?: boolean;
  /** Maximum events before snapshot recommendation */
  snapshotThreshold?: number;
}

const DEFAULT_CONFIG: Required<RvfEventLogConfig> = {
  logPath: 'events.rvf',
  verbose: false,

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Strip NULs at the source: logPath.replace(/\0/g, '') — but prefer fixing the upstream producer
  2. Decode buffers on their exact byte range (buf.toString('utf8', start, end)) instead of converting NUL-padded buffers wholesale
  3. Validate externally supplied paths with the same includes('\0') check before constructing RvfEventLog

Example fix

// before
const logPath = buf.toString(); // may contain NUL padding
const log = new RvfEventLog({ logPath }); // throws

// after
const logPath = buf.subarray(0, buf.indexOf(0)).toString('utf8');
const log = new RvfEventLog({ logPath });
Defensive patterns

Strategy: validation

Validate before calling

function safeLogPath(p: string): string {
  if (p.includes('\0')) throw new Error('log path contains NUL bytes');
  return p;
}
const log = new RvfEventLog({ logPath: safeLogPath(fromEnv) });

Type guard

function isValidPath(p: unknown): p is string {
  return typeof p === 'string' && p.length > 0 && !p.includes('\0');
}

Prevention

When it happens

Trigger: Passing a logPath built from env vars or CLI input containing a NUL byte; strings decoded from fixed-length buffers padded with NULs and not trimmed; template concatenation that pulls binary data into a path.

Common situations: Reading paths from IPC messages or C-style buffers sliced mid-string; config values pasted with invisible control characters; mis-decoded multibyte input producing NUL padding.

Related errors


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