koala73/worldmonitor · error · ConvexError
ACCOUNT_OWNER_FENCE_CONFLICT
ACCOUNT_OWNER_FENCE_CONFLICT
Error message
ACCOUNT_OWNER_FENCE_CONFLICT
What it means
Account-lookup fence conflict raised via findAccountByOwnerFence: the owner-fence hash candidate resolution produced a conflicting or ambiguous match among companyMonitoringAccounts rows. The owner fence hash binds an account to exactly one owner identity, so a conflict means the account-to-owner mapping is inconsistent — a fence-hash collision or a stale duplicate account.
Solutions
- Inspect all companyMonitoringAccounts rows matching the ownerFenceHash candidates for duplicates or stale rows
- If a stale duplicate exists, let the purge/reaper flow terminalize it rather than manually patching fences
- Verify the owner-fence hash computation inputs (owner identity fields) have not changed format
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at convex/companyMonitoring/accounts.ts:122 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/d4ad12d1779ddb4c.
Report an issue: GitHub.
Appendix: source
Thrown at convex/companyMonitoring/accounts.ts:122
Math.max(0, delayMs),
internal.companyMonitoring.accounts.advanceAccountPurge,
{ ownerFenceHash, purgeGeneration },
);
}
async function findAccountByOwnerFence(
ctx: MutationCtx,
ownerFence: CompanyMonitoringOwnerFenceCandidates,
): Promise<{ account: Doc<"companyMonitoringAccounts">; matchedHash: string } | null> {
let match: { account: Doc<"companyMonitoringAccounts">; matchedHash: string } | null = null;
for (const ownerFenceHash of ownerFence.all) {
const account = await ctx.db
.query("companyMonitoringAccounts")
.withIndex("by_ownerFenceHash", (q) => q.eq("ownerFenceHash", ownerFenceHash))
.unique();
if (!account) continue;
if (match && match.account._id !== account._id) {
throw new ConvexError("ACCOUNT_OWNER_FENCE_CONFLICT");
}
match = { account, matchedHash: ownerFenceHash };
}
return match;
}
async function findAccountByOwnerUserId(
ctx: MutationCtx,
ownerUserId: string,
): Promise<Doc<"companyMonitoringAccounts"> | null> {
const accounts = await ctx.db
.query("companyMonitoringAccounts")
.withIndex("by_ownerUserId", (q) => q.eq("ownerUserId", ownerUserId))
.take(2);
if (accounts.length > 1) throw new ConvexError("ACCOUNT_OWNER_FENCE_CONFLICT");
return accounts[0] ?? null;
}
View on GitHub (pinned to eeab0a219f)