santifer/career-ops · error · Error
Malformed benchmarks file at ${path}: expected a top-level "
Error message
Malformed benchmarks file at ${path}: expected a top-level "benchmarks" map What it means
The benchmarks YAML loaded successfully but the top-level structure is wrong: doc.benchmarks must be a non-null object (a map of metric keys like response_rate, application_to_interview). This fires when benchmarks is missing, is an array, is a string, or is explicitly null.
Source
Thrown at funnel-velocity.mjs:231
sameDayExcluded,
censored,
};
}
return result;
}
// --- Benchmarks ---
export function loadBenchmarks(explicitPath) {
const path = explicitPath
|| (existsSync(join(CAREER_OPS, 'config/benchmarks.yml')) ? join(CAREER_OPS, 'config/benchmarks.yml') : join(CAREER_OPS, 'templates/benchmarks.yml'));
let doc;
try {
doc = yaml.load(readFileSync(path, 'utf-8'));
} catch (err) {
throw new Error(`Cannot read benchmarks at ${path}: ${err.message}`);
}
if (!doc || typeof doc.benchmarks !== 'object' || doc.benchmarks === null) {
throw new Error(`Malformed benchmarks file at ${path}: expected a top-level "benchmarks" map`);
}
return { benchmarks: doc.benchmarks, path };
}
/** Classify an own-rate percentage against a benchmark's range (inclusive). */
export function classify(ownPct, metric) {
if (ownPct === null || ownPct === undefined || !metric || !Array.isArray(metric.range_pct)) return null;
const [lo, hi] = metric.range_pct;
const band = ownPct < lo ? 'below-range' : ownPct > hi ? 'above-range' : 'within-range';
const typical = metric.typical_pct;
return {
band,
ownPct,
rangePct: [lo, hi],
typicalPct: typical ?? null,
vsTypical: typical ? Math.round((ownPct / typical) * 10) / 10 : null,
source: metric.source ?? null,
year: metric.year ?? null,View on GitHub (pinned to 9b17a8ac97)
Solutions
- Ensure the YAML has a top-level benchmarks: key mapping to an object, e.g. benchmarks:\n response_rate:\n range_pct: [2, 13].
- Compare against templates/benchmarks.yml for the expected structure.
- Validate with node -e "const d=require('js-yaml').load(require('fs').readFileSync('config/benchmarks.yml','utf-8')); console.log(typeof d.benchmarks, d.benchmarks)".
Example fix
# before (malformed)
benchmarks:
- response_rate
- application_to_interview
# after
benchmarks:
response_rate:
range_pct: [2, 13]
typical_pct: 3
year: 2025
application_to_interview:
range_pct: [3, 15]
typical_pct: 5
year: 2025 Defensive patterns
Strategy: validation
Validate before calling
import * as yaml from 'js-yaml';
import { readFileSync } from 'fs';
function validateBenchmarksShape(path) {
const doc = yaml.load(readFileSync(path, 'utf-8'));
if (!doc || typeof doc.benchmarks !== 'object' || doc.benchmarks === null) {
throw new Error(`Expected top-level "benchmarks" object map in ${path}`);
}
return doc.benchmarks;
} Type guard
/** @param {unknown} doc */
function isBenchmarksDoc(doc) {
return (
typeof doc === 'object' && doc !== null &&
'benchmarks' in doc &&
typeof doc.benchmarks === 'object' &&
doc.benchmarks !== null &&
!Array.isArray(doc.benchmarks)
);
} Prevention
- Always use a top-level benchmarks: key mapping to an object, not an array or list.
- Compare custom config/benchmarks.yml against templates/benchmarks.yml for structure.
- Run the module's --self-test to catch structural regressions.
When it happens
Trigger: The YAML has a top-level array instead of a map; the key is misspelled (benchmark: instead of benchmarks:); benchmarks: is present but empty/null; indentation nests benchmarks under another key so it is not top-level.
Common situations: User hand-edits config/benchmarks.yml and renames or restructures the key; a YAML indentation error pushes benchmarks under a parent key; the file was replaced with a flat list.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Cannot read benchmarks at ${path}: ${err.message}
- arbeitsagentur: entry "${entry.name || '(unnamed)'}" has no
- Unsupported profile photo style: ${style} (expected rounded,
- gmail: invalid days_back "${ctx?.settings?.days_back}" (must
- ashby: cannot derive API URL for ${entry.name}
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/30ec0427f5b3a927.
Report an issue: GitHub.