koala73/worldmonitor · error · ConvexError

INVALID_COMPANY_PATCH

Error message

INVALID_COMPANY_PATCH

What it means

Thrown by updateCompanyForOwner when the patch's claim mutation arrays exceed COMPANY_MONITORING_LIMITS.maxClaimsPerCompany. The check runs on the raw addClaims and removeClaimIds lengths before any deduplication, so the limit applies to the request size, not the resulting claim set.

Source

Thrown at convex/companyMonitoring/companies.ts:211

  handler: async (ctx, args) => {
    const account = await requireActiveAccount(ctx, args.ownerUserId);
    const company = await ctx.db
      .query("companyMonitoringCompanies")
      .withIndex("by_account_companyId", (q) =>
        q.eq("ownerAccountId", account.logicalAccountId).eq("companyId", args.companyId),
      )
      .unique();
    if (!company || company.lifecycle === "removed" || !company.name || !company.domicileCountry) {
      throw new ConvexError("NOT_FOUND");
    }
    const patch = args.patch;
    const addClaimInputs = patch.addClaims ?? [];
    const removeClaimInputs = patch.removeClaimIds ?? [];
    if (
      addClaimInputs.length > COMPANY_MONITORING_LIMITS.maxClaimsPerCompany ||
      removeClaimInputs.length > COMPANY_MONITORING_LIMITS.maxClaimsPerCompany
    ) {
      throw new ConvexError("INVALID_COMPANY_PATCH");
    }

    const hasName = Object.prototype.hasOwnProperty.call(patch, "name");
    const hasDomicile = Object.prototype.hasOwnProperty.call(patch, "domicileCountry");
    const hasCustomerReference = Object.prototype.hasOwnProperty.call(patch, "customerReference");
    const normalizedFields = normalizeMonitoredCompanyInput({
      name: hasName ? patch.name! : company.name,
      domicileCountry: hasDomicile ? patch.domicileCountry! : company.domicileCountry,
      customerReference: hasCustomerReference
        ? patch.customerReference
        : company.customerReference,
    });
    if (hasCustomerReference && normalizedFields.customerReference) {
      const conflict = await findNoopByCustomerReference(
        ctx,
        account.logicalAccountId,
        normalizedFields.customerReference,
      );

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Split the claim additions/removals into batches each no larger than COMPANY_MONITORING_LIMITS.maxClaimsPerCompany.
  2. Read the limit from the shared company-monitoring-contract on the client and cap the patch size before sending.
  3. Prefer targeted single-claim edits over wholesale list replacement.

Example fix

// before
await update({ companyId, patch: { addClaims: allClaims, removeClaimIds: allRemovals } });

// after
const LIMIT = COMPANY_MONITORING_LIMITS.maxClaimsPerCompany;
for (let i = 0; i < allClaims.length; i += LIMIT) {
  await update({ companyId, patch: { addClaims: allClaims.slice(i, i + LIMIT) } });
}
for (let i = 0; i < allRemovals.length; i += LIMIT) {
  await update({ companyId, patch: { removeClaimIds: allRemovals.slice(i, i + LIMIT) } });
}
Defensive patterns

Strategy: validation

Validate before calling

import { COMPANY_MONITORING_LIMITS } from "shared/company-monitoring-contract";
const LIMIT = COMPANY_MONITORING_LIMITS.maxClaimsPerCompany;
if ((patch.addClaims?.length ?? 0) > LIMIT || (patch.removeClaimIds?.length ?? 0) > LIMIT) {
  throw new Error("Claim patch exceeds per-company limit");
}

Type guard

function patchWithinClaimLimit(patch: { addClaims?: unknown[]; removeClaimIds?: unknown[] }, limit: number): boolean {
  return (patch.addClaims?.length ?? 0) <= limit && (patch.removeClaimIds?.length ?? 0) <= limit;
}

Prevention

When it happens

Trigger: Submitting a patch with addClaims.length > maxClaimsPerCompany or removeClaimIds.length > maxClaimsPerCompany in a single updateCompanyForOwner call.

Common situations: Bulk-import UI that sends the entire claim list in one patch; a migration script that batches too many claim edits per company; client not paginating claim removals.

Related errors


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