Big-Little bulk operations (admin)
The chapter-level Big-Little flow (one mentee proposes, the mentor accepts) is great for normal recruitment, but it breaks down in two real scenarios:
- Onboarding an org with legacy data. A new tenant arrives with hundreds of historical big/little pairs in a spreadsheet. Re-creating each pairing through on-behalf-of proposals isn't feasible.
- Fixing misassignments. A pair was set up incorrectly, a member relocated, or a misclick stuck two members in the wrong family branch. There's no member-side affordance to undo it.
Both of those are now backed by direct admin actions, available to national and platform admins.
Reverse a Big-Little pairing
Use this when an existing pair needs to be unwound — relocation, misassignment, etc. The action clears MemberProfile.big for the chosen member.
Where to find it
Open the member detail page for the little (the one with a big set) and click the Reverse pairing action in the Big-Little card. National/platform admin only; the action is hidden for everyone else.
What it does
- Sets the little's
bigtonull. - Audit-logged with the actor, target member, prior big, and a timestamp.
- Idempotent — calling it on a member who already has no big returns 400 with a clear message rather than silently succeeding.
What it doesn't do
- Does not delete the big member's other relationships (their other littles stay).
- Does not move the little's downstream littles (their family tree below them is preserved; only the link upward is cleared).
- Does not notify the affected members.
If you want to re-pair them, you can use the regular member-side proposal flow or the bulk import below.
Bulk import pairings (XLSX / CSV)
Use this when onboarding a tenant with historical Big-Little data, or any time you need to set many pairings at once.
File format
Upload an XLSX or CSV with one row per pairing. Columns:
| Column | Identifier kind | Required |
|---|---|---|
little_email or little_org_member_name | Email lookup or fallback org_member_name lookup | Yes (one of the two) |
big_email or big_org_member_name | Same | Yes (one of the two) |
Use email when you have it — it's the most reliable. Fall back to org_member_name (the fraternal / sorority name) when you don't, but expect more "could not resolve" errors.
Where to find it
Open Org → Members → Big-Little Bulk Import, then upload the file. The page is gated to national/platform admin.
Response
The import returns a structured result:
{
"paired": 142,
"skipped": 3,
"errors": [
{"row": 17, "reason": "could not resolve little email 'old@stale.example'"},
{"row": 38, "reason": "cycle detected: A → B → A"},
{"row": 91, "reason": "little already has a big — pass overwrite=true to replace"}
]
}
paired is the count of new pairings created. skipped is rows that were valid but produced no change (already pointing at the proposed big). errors is per-row, with the spreadsheet row number so you can fix the source file and re-upload.
Cycle detection
The import walks up the proposed big's ancestor chain before committing each row. If the chain reaches back to the proposed little, the row is rejected with a cycle detected error. Family trees should always be DAGs — cycles indicate bad source data.
Overwriting existing pairings
By default, rows that would overwrite an existing big are rejected with a per-row error. Set the overwrite=true form field (or check the Overwrite existing checkbox in the UI) to replace existing pairings with the new ones from the file. Use sparingly — this can mass-reset family trees with no undo.
Per-batch progress
For large imports the resolution phase (mapping emails / names to memberships and walking ancestry) can take a while. The admin UI polls bulk_import.result_summary["relationship_resolution"] every 25 rows and updates a progress indicator ("Pass 2: relationship resolution 142 of 312") so you don't see a stuck progress bar.
Retry on transient errors
The second-pass save uses a 3-attempt retry with linear backoff for transient OperationalErrors (concurrent imports, signal cascades briefly raising PG locks). A row that fails three times in a row propagates the error rather than silently dropping — you'll see it in the response's errors array.
Audit log
Both reverse and bulk-import operations write to the platform audit log:
- Reverse:
operation="big_little_reverse",resource_type="member", with the priorbig_idin metadata. - Bulk import:
operation="big_little_bulk_import", with the paired count, skipped count, and a summary of the first 50 errors in metadata. The file itself is not retained.
Open Settings → Audit Log to review.
Common failure modes
- "Could not resolve email" — the email isn't in your org's user roster. Either add the member first or use
org_member_nameif you only have the fraternal name. - "Cycle detected" — fix the source data; family trees shouldn't loop.
- "Little already has a big" without
overwrite=true— review whether you actually want to replace, then re-upload with the flag set. - "Cross-org pair rejected" — both the big and the little must be in chapters of your organization. Cross-org pairings aren't allowed.
Related
- Family tree (member view)
- Family tree admin — the regular member-driven flow.
- Audit log retention — how long the records persist.
Last verified against v0.63.39 (2026-06-26). Reverse + bulk import + per-batch progress + retry shipped v0.63.36.