affaan-m/ECC · error · Error

Could not allocate a snapshot filename for session ${session

Error message

Could not allocate a snapshot filename for session ${session.sessionId}

What it means

When writing status snapshots, the script builds a unique filename per session by appending an empty/hash/numeric suffix and checking a usedNames Set; if 1000 consecutive candidates are all taken it gives up and throws. Reaching it means the baseName plus the hashSuffix plus 0..1000 all collided, which is effectively impossible unless every session in the payload shares the same sessionId-derived baseName (a degenerate input).

Source

Thrown at scripts/loop-status.js:674

  }
}

function getSnapshotPath(outputDir, session, usedNames) {
  const baseName = sanitizeSnapshotName(session.sessionId);
  const hashSuffix = hashString(session.transcriptPath || session.sessionId).slice(0, 8);
  let attempt = 0;

  while (attempt < 1000) {
    const suffix = attempt === 0 ? '' : `-${hashSuffix}${attempt === 1 ? '' : `-${attempt}`}`;
    const fileName = `${baseName}${suffix}.json`;
    if (!usedNames.has(fileName)) {
      usedNames.add(fileName);
      return path.join(outputDir, fileName);
    }
    attempt += 1;
  }

  throw new Error(`Could not allocate a snapshot filename for session ${session.sessionId}`);
}

function writeStatusSnapshots(payload, writeDir) {
  if (!writeDir) {
    return null;
  }

  const outputDir = path.resolve(writeDir);
  fs.mkdirSync(outputDir, { recursive: true });

  const usedNames = new Set(['index.json']);
  const sessions = payload.sessions.map(session => {
    const snapshotPath = getSnapshotPath(outputDir, session, usedNames);
    atomicWriteJson(snapshotPath, {
      generatedAt: payload.generatedAt,
      schemaVersion: 'ecc.loop-status.session.v1',
      session,
    });

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Dedupe the sessions payload before writing so each baseName is distinct.
  2. Use a fresh/empty --write-dir per run to avoid pre-populating usedNames with leftover files.
  3. If genuinely writing >1000 snapshots, shard into multiple output directories.
  4. Treat hitting this error as a data-integrity signal: inspect why sessionIds collide.

Example fix

// before — duplicate sessions cause baseName collisions
const sessions = payload.sessions; // contains many dupes

// after — dedupe by sessionId before snapshotting
const seen = new Set();
const sessions = payload.sessions.filter(s => {
  if (seen.has(s.sessionId)) return false;
  seen.add(s.sessionId);
  return true;
});
Defensive patterns

Strategy: fallback

Validate before calling

// Dedupe sessions by sessionId before snapshotting so baseNames are distinct.
function dedupeSessions(sessions) {
  const seen = new Set();
  return sessions.filter(s => {
    if (!s || !s.sessionId || seen.has(s.sessionId)) return false;
    seen.add(s.sessionId);
    return true;
  });
}

Try / catch

try { writeStatusSnapshots(payload, writeDir); }
catch (err) {
  if (/Could not allocate a snapshot filename/.test(err.message)) {
    // Fallback: shard into a subdir per batch, or clear writeDir and retry with deduped payload.
    writeStatusSnapshots({ ...payload, sessions: dedupeSessions(payload.sessions) }, writeDir);
  } else throw err;
}

Prevention

When it happens

Trigger: A payload.sessions array containing hundreds of sessions whose baseName is identical (e.g. all sessions report the same sessionId, so every hashSuffix is the same and only the counter differentiates — but the counter would still resolve within 1000). Realistically only hit with a corrupted/duplicated session list fed to writeStatusSnapshots.

Common situations: A bug upstream that duplicates session records with identical ids. Running writeStatusSnapshots twice into the same writeDir without clearing it, while also feeding an enormous identical-session payload. Essentially a guard rail rather than a user-facing condition.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/28df09f8b9de2ecc. Report an issue: GitHub.