OtterMind/Chat2DB · error · AggregateError

Failed to persist cleanup and roll back assignment changes.

Error message

Failed to persist cleanup and roll back assignment changes.

What it means

This AggregateError is thrown in the claim-cleanup flow when two operations fail in sequence: first, upsertStateComment (persisting the released-claim state to a GitHub issue comment) fails, and then the rollback of appliedEffects (re-adding the removed assignee) also fails. The AggregateError bundles both errors so neither is lost. This is a defensive transactional pattern: it tries to undo the assignee removal when state persistence fails, and if the undo itself fails, it signals total inconsistency.

Source

Thrown at script/github/issue-claim.js:691

    updatedAt: now,
    reason,
  };
  const messages = {
    issue_closed: `@${state.claimant}'s claim was released because the issue was closed.`,
    task_unpublished: `@${state.claimant}'s claim was released because this is no longer a published contribution task.`,
    assignment_removed: `@${state.claimant}'s claim was released after the assignment was removed.`,
  };
  try {
    await client.upsertStateComment(
      issue.number,
      record,
      renderStateComment(state, messages[reason], policy),
    );
  } catch (error) {
    try {
      await rollbackEffects(client, issue.number, appliedEffects);
    } catch (rollbackError) {
      throw new AggregateError(
        [error, rollbackError],
        'Failed to persist cleanup and roll back assignment changes.',
      );
    }
    throw error;
  }
  return reason;
}

async function main() {
  const mode = process.argv[2];
  const policyPath = process.env.CLAIM_POLICY_PATH
    || path.resolve(process.cwd(), '.github/claim-policy.json');
  const policy = loadPolicy(policyPath);
  const client = new GitHubClient({
    token: process.env.GITHUB_TOKEN,
    repository: process.env.GITHUB_REPOSITORY,
    apiUrl: process.env.GITHUB_API_URL,

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Inspect error.errors array (the AggregateError exposes both the original and rollback errors) to identify the root API failure.
  2. Check GITHUB_TOKEN validity and repository write permissions.
  3. Check GitHub API rate limit status (X-RateLimit-Remaining headers).
  4. Re-run the cleanup after resolving the API access issue; the script is idempotent for state transitions.

Example fix

// before
await client.upsertStateComment(issue.number, record, body);

// after
try {
  await client.upsertStateComment(issue.number, record, body);
} catch (e) {
  if (e instanceof AggregateError) {
    for (const inner of e.errors) {
      console.error('Cleanup failure detail:', inner);
    }
    // alert operator for manual reconciliation
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Type guard

function isAggregateError(e: unknown): e is AggregateError {
  return e instanceof AggregateError && Array.isArray(e.errors);
}

Try / catch

try {
  await cleanupClaim({ client, policy, event });
} catch (e) {
  if (e instanceof AggregateError) {
    for (const inner of e.errors) {
      console.error('Cleanup failure detail:', inner?.message ?? inner);
    }
    // manual reconciliation required — state may be inconsistent
    process.exitCode = 2;
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Running issue-claim.js in 'cleanup' mode (or during 'event' processing that triggers cleanup) where: (1) the GitHub API call to upsert the state comment fails (rate limit, network, auth), AND (2) the subsequent rollback call to re-add the assignee via applyEffects also fails. Both must fail to produce this specific AggregateError.

Common situations: GitHub API rate limiting (403) causing both the comment and the assignee restore to fail. GITHUB_TOKEN expired or revoked between calls. Network outage during the cleanup transaction. Repository permissions changed mid-run.

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/54e8045438c94c2a. Report an issue: GitHub.