Crosstalk-Solutions/project-nomad · error · Error
sysbench disk-write benchmark produced no parseable MiB/s —
Error message
sysbench disk-write benchmark produced no parseable MiB/s — aborting
What it means
Thrown by BenchmarkService after running a sysbench disk-write benchmark inside a container when the regex parsing of sysbench's stdout fails to extract a positive, finite MiB/s value. The code deliberately fails loudly (throwing instead of returning 0) because MiB/s is the primary scored metric, so a silent zero would corrupt benchmark scoring.
Source
Thrown at admin/app/services/benchmark_service.ts:1556
// --file-extra-flags=direct (O_DIRECT) on the run bypasses the page cache (W4).
const output = await this._runSysbenchCommand([
'sh',
'-c',
'sysbench fileio --file-total-size=1G --file-num=4 prepare && ' +
'sysbench fileio --file-total-size=1G --file-num=4 --file-test-mode=seqwr --file-extra-flags=direct --time=30 run && ' +
'sysbench fileio --file-total-size=1G --file-num=4 cleanup',
])
// Parse output - look for the Throughput section
const writeMatch = output.match(/written,\s*MiB\/s:\s*([\d.]+)/i)
const writesPerSecMatch = output.match(/writes\/s:\s*([\d.]+)/i)
logger.debug(`[BenchmarkService] Disk write output parsing - written: ${writeMatch?.[1]}, writes/s: ${writesPerSecMatch?.[1]}`)
// Scored primary metric: fail loudly instead of silently scoring zero on a parse miss
const writeMbPerSec = writeMatch ? parseFloat(writeMatch[1]) : Number.NaN
if (!writeMatch || !Number.isFinite(writeMbPerSec) || writeMbPerSec <= 0) {
throw new Error('sysbench disk-write benchmark produced no parseable MiB/s — aborting')
}
return {
reads_per_second: 0,
writes_per_second: writesPerSecMatch ? parseFloat(writesPerSecMatch[1]) : 0,
read_mb_per_sec: 0,
write_mb_per_sec: writeMbPerSec,
total_time: 30,
}
}
/**
* Run a sysbench command in a Docker container
*/
private async _runSysbenchCommand(cmd: string[]): Promise<string> {
let container: Dockerode.Container | null = null
try {
// Create container with TTY to avoid multiplexed outputView on GitHub (pinned to 0bd1c6f4f9)
Solutions
- Inspect the captured sysbench stdout (add a logger.debug of the raw output) and compare it against the writeMatch regex; adjust the regex to the actual format
- Pin the sysbench/toolbox container image and version so output format is stable
- Set LC_ALL=C (or an English locale) in the container env so number formatting is deterministic
- Guard upstream: verify the sysbench command exits with code 0 before parsing, and treat non-zero exits as a distinct error
- If a '0 MiB/s' result is legitimately possible in your environment, decide on an explicit floor value instead of relying on the parser to reject it
Example fix
// before
const writeMbPerSec = writeMatch ? parseFloat(writeMatch[1]) : Number.NaN
if (!writeMatch || !Number.isFinite(writeMbPerSec) || writeMbPerSec <= 0) {
throw new Error('sysbench disk-write benchmark produced no parseable MiB/s — aborting')
}
// after
const writeMbPerSec = writeMatch ? Number.parseFloat(writeMatch[1].replace(',', '.')) : Number.NaN
if (!writeMatch || !Number.isFinite(writeMbPerSec) || writeMbPerSec <= 0) {
logger.error(`[BenchmarkService] Unparseable sysbench output:\n${rawOutput}`)
throw new Error('sysbench disk-write benchmark produced no parseable MiB/s — aborting')
} Defensive patterns
Strategy: validation
Validate before calling
const m = /([\d.]+)\s*MiB\/s/.exec(stdout)
if (!m || !Number.isFinite(parseFloat(m[1].replace(',', '.'))) || parseFloat(m[1]) <= 0) {
throw new Error('Skip benchmark: sysbench output format unrecognized')
} Type guard
function hasValidWriteMiBs(stdout: string): boolean {
const m = /([\d.]+)\s*MiB\/s/.exec(stdout)
return !!m && Number.isFinite(Number.parseFloat(m[1].replace(',', '.'))) && Number(m[1]) > 0
} Try / catch
try { runDiskWriteBenchmark() } catch (e) { if (e instanceof Error && e.message.includes('no parseable MiB/s')) { /* surface parse failure, keep prior stages' results */ } else throw e } Prevention
- Pin the sysbench container image version so output format is stable
- Set LC_ALL=C inside the benchmark container
- Log raw stdout on every parse attempt so format drift is diagnosable
- Add a format smoke test that asserts the regex matches known sysbench output fixtures
When it happens
Trigger: Running the disk-write benchmark stage where sysbench output format differs from the expected 'MiB/s' regex (e.g. sysbench version differences, locale-adjusted decimal separators, output polluted by container logs/warnings), sysbench exiting before printing results, or parseFloat yielding NaN/0 because the matched group was malformed.
Common situations: Upgrading sysbench or the Docker image so output lines change (e.g. 'transferred (X MiB/s)' wording changes), non-English locale printing commas as decimal separators, OOM/killed container producing truncated output, or a changed block-size/files flag causing sysbench to print a different summary layout.
Related errors
- Sysbench command failed: ${error.message}
- Failed to get auth token from ${registry}: ${response.status
- No token returned from ${registry}
- recreated container ${readiness.reason}
- Error parsing content: ${(error as Error).message}
AI-assisted analysis of Crosstalk-Solutions/project-nomad@0bd1c6f4f9 (2026-08-27).
Data as JSON: /api/errors/4b986b8078583cfa.
Report an issue: GitHub.