koala73/worldmonitor · error · ConvexError

COMPANY_MONITORING_ACCOUNT_INACTIVE

Error message

COMPANY_MONITORING_ACCOUNT_INACTIVE

What it means

Thrown by ingestCompanyEvidenceForCompanyIds when the owner account row is missing, its lifecycle is not 'entitled', or it carries a terminalReason. Evidence ingestion is only permitted for fully-entitled accounts that have not been terminally deactivated.

Source

Thrown at convex/companyMonitoring/evidence.ts:371

}

export async function ingestCompanyEvidenceForCompanyIds(
  ctx: MutationCtx,
  input: {
    ownerAccountId: string;
    companyIds: string[];
    evidence: ProviderEvidence[];
  },
) {
  if (input.evidence.length === 0 || input.evidence.length > MAX_INGESTION_ROWS) {
    throw new ConvexError("COMPANY_MONITORING_EVIDENCE_BATCH_INVALID");
  }
  const account = await ctx.db
    .query("companyMonitoringAccounts")
    .withIndex("by_logicalAccountId", (q) => q.eq("logicalAccountId", input.ownerAccountId))
    .unique();
  if (!account || account.lifecycle !== "entitled" || account.terminalReason) {
    throw new ConvexError("COMPANY_MONITORING_ACCOUNT_INACTIVE");
  }
  const subjects = await canonicalSubjects(ctx, input.ownerAccountId, input.companyIds);
  const normalized = await normalizeCompanyEvidence({
    ownerAccountId: input.ownerAccountId,
    subjects,
    evidence: input.evidence,
    now: Date.now(),
  });
  if (normalized.evidence.length > MAX_EXPANDED_EVIDENCE_ROWS) {
    throw new ConvexError("COMPANY_MONITORING_EVIDENCE_EXPANSION_INVALID");
  }
  const now = Date.now();
  const affected = new Map<string, Map<string, "evidence_unavailable" | undefined>>();
  const rememberOccurrence = (
    companyId: string,
    occurrenceDedupeKey: string,
    fallbackLossReason?: "evidence_unavailable",
  ) => {

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Before ingesting, verify the account is lifecycle 'entitled' with no terminalReason.
  2. On this error, stop retrying work for the account and surface it for entitlement review.
  3. Ensure account teardown cancels in-flight obligations before marking the account terminal.

Example fix

// before
await ingest({ ownerAccountId, companyIds, evidence });

// after
const account = await fetchAccount(ownerAccountId);
if (!account || account.lifecycle !== "entitled" || account.terminalReason) {
  return { status: "account_inactive" };
}
await ingest({ ownerAccountId, companyIds, evidence });
Defensive patterns

Strategy: validation

Validate before calling

const account = await fetchAccount(ownerAccountId);
if (!account || account.lifecycle !== "entitled" || account.terminalReason) {
  return { status: "account_inactive" };
}

Type guard

function isEntitledAccount(a: { lifecycle: string; terminalReason?: string } | null): boolean {
  return Boolean(a) && a.lifecycle === "entitled" && !a.terminalReason;
}

Prevention

When it happens

Trigger: Ingesting evidence for an ownerAccountId whose companyMonitoringAccounts row has lifecycle other than 'entitled' (e.g., 'suspended', 'cancelled') or has a terminalReason set.

Common situations: Account suspended/cancelled between when a scan was scheduled and when the worker returns evidence; billing lapse setting terminalReason; worker retrying an old lease after account teardown.

Related errors


AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12). Data as JSON: /api/errors/15b3e95a78dd0edb. Report an issue: GitHub.