santifer/career-ops · warning

Could not release report reservation

Error message

Could not release report reservation: ${e.message}

What it means

After a pipeline run, the code releases the report-number range it reserved via reserve-report-num.mjs so stale reservations don't block future runs. If the release call itself fails, the run's result is still returned (the release is in a `finally`), and only this warning is printed — the reservation may remain until its 4-hour GC window expires.

Solutions

  1. Check that the `reports/` directory exists and is writable by the process running the script.
  2. If the run itself succeeded, ignore the warning: stale sentinels are garbage-collected after 4h, or free the range manually with `node reserve-report-num.mjs --release <range>`.
  3. Re-run the release manually if you need the numbers back immediately.
  4. Look for concurrent pipelines sharing the same reportsDir and serialize them.

Example fix

// before
// warning appears; reservation leaks until GC
// after (manual cleanup)
node reserve-report-num.mjs --release 042-049
Defensive patterns

Strategy: try-catch

Validate before calling

const fs = require('fs');
const dir = path.join(__dirname, 'reports');
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
fs.accessSync(dir, fs.constants.W_OK);

Try / catch

try {
  await releaseReportNumbers(reservedNumbers, { reportsDir });
} catch (e) {
  console.warn(`Could not release report reservation: ${e.message}`);
  // release manually within 4h: node reserve-report-num.mjs --release <range>
}

Prevention

When it happens

Trigger: releaseReportNumbers(reservedNumbers, { reportsDir }) throwing: reports directory missing/unwritable, a filesystem error while scanning sentinel files, or a corrupted/locked sentinel in the reservation mechanism.

Common situations: Running the pipeline in a container where reports/ is read-only or was never created; concurrent workers racing on the same reservation files; deleting reports/ mid-run.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/99e895f9a7e11c81. Report an issue: GitHub.

Appendix: source

Thrown at openrouter-runner.mjs:742

    const tsvFile     = `batch/tracker-additions/or-${numStr}-${slug}.tsv`;
    // Header row, then the single data row. merge-tracker.mjs resolves the
    // fields by NAME when the header is present (#3517), so this row cannot be
    // read into the wrong columns. (Headerless files still work; they are the
    // legacy form, and they are the ones that can hit the undecidable
    // score-vs-status case.)
    writeFile(tsvFile, `${TSV_ADDITION_HEADER}\n${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 aac998c7ed)