santifer/career-ops · warning
Could not release report reservation: ${e.message}
Error message
Could not release report reservation: ${e.message} What it means
After writing a report, openrouter-runner.mjs's finally block calls releaseReportNumbers() (imported from reserve-report-num.mjs) to delete the NNN-RESERVED.md sentinel files that claim its report-number slots. If that release throws -- typically ENOENT because the sentinel was already deleted by verify-pipeline's stale GC or another release -- the warn fires and the reservation leaks; leaked sentinels expire on their own after 4 hours.
Source
Thrown at openrouter-runner.mjs:698
const tsvFile = `batch/tracker-additions/or-${numStr}-${slug}.tsv`;
// AGENTS.md: a tracker-addition TSV is a SINGLE data line of 9 tab-separated
// columns. merge-tracker.mjs reads the whole file as ONE record (no line
// splitting), so a leading header row makes parts[4]/parts[5] the literal
// "status"/"score" and the evaluation is skipped ("cannot tell score from
// status"). Write only the data line.
writeFile(tsvFile, tsvLine);
console.log(`\n✅ Report saved: ${relPath}`);
console.log('\n─── EVALUATION ──────────────────────────────────────\n');
console.log(result);
console.log('\n─────────────────────────────────────────────────────\n');
return relPath;
} finally {
try {
await releaseReportNumbers(reservedNumbers, { reportsDir: path.join(__dirname, 'reports') });
} catch (e) {
console.warn(`Could not release report reservation: ${e.message}`);
}
}
}
// -- PIPELINE --
async function cmdPipeline(ctx) {
const pending = readPipeline();
if (pending.length === 0) {
console.log('No pending listings in pipeline.md.');
return;
}
console.log(`Processing ${pending.length} pending listing(s) from pipeline.md...\n`);
for (let i = 0; i < pending.length; i++) {
const item = pending[i];
console.log(`\n[${i + 1}/${pending.length}] ${item.company} — ${item.role}`);
try {View on GitHub (pinned to 60398d6549)
Solutions
- Manually free the range: node reserve-report-num.mjs --release NNN-MMM.
- Or run node verify-pipeline.mjs -- sentinels older than 4h are GC'd automatically and reported as 'Removed stale reservation sentinel'.
- If release keeps failing on a live sentinel, check permissions on reports/ (ls -la reports/ | grep RESERVED).
Example fix
// before: any release error surfaces as a generic warn
try { await releaseReportNumbers(reservedNumbers, opts); }
catch (e) { console.warn(`Could not release report reservation: ${e.message}`); }
// after: tolerate the benign already-deleted race
try { await releaseReportNumbers(reservedNumbers, opts); }
catch (e) {
if (!/ENOENT/.test(e.message)) console.warn(`Could not release report reservation: ${e.message}`);
} Defensive patterns
Strategy: try-catch
Try / catch
// Release in finally, and treat an already-deleted sentinel as success
try {
await writeReports(reservedNumbers);
} finally {
try {
await releaseReportNumbers(reservedNumbers, { reportsDir: REPORTS_DIR });
} catch (e) {
if (e.code !== 'ENOENT') throw e; // someone else GC'd/released it: benign
}
} Prevention
- Always wrap reservation usage in try/finally with releaseReportNumbers in the finally block.
- Don't run verify-pipeline's sentinel GC in parallel with live batch workers — the 4h age check makes overlap mostly safe, but release races still warn.
- If a leak happens anyway, node reserve-report-num.mjs --release NNN-MMM or verify-pipeline after 4h cleans it up.
When it happens
Trigger: A batch run overlapping verify-pipeline.mjs, which unlinks sentinels older than 4h while the worker is still finishing; filesystem errors or permission changes on reports/ between reservation and release; two code paths releasing the same range.
Common situations: Long batch evaluations running concurrently with health checks; interrupted processes on CI; NFS/latency-prone mounts where unlink races are common.
Related errors
- ⚠️ Could not release report reservation: ${err.message}
- Could not claim ${count} report slot(s) after ${MAX_RETRIES}
- ⚠️ Browser cleanup failed: ${err.message}
- ⚠️ Page cleanup failed: ${err.message}
- ⚠️ Context cleanup failed: ${err.message}
AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20).
Data as JSON: /api/errors/99e895f9a7e11c81.
Report an issue: GitHub.