koala73/worldmonitor · error · ConvexError

COUNTRY_LOCKS_NOT_SEEDED

COUNTRY_LOCKS_NOT_SEEDED

Error message

COUNTRY_LOCKS_NOT_SEEDED

What it means

Infrastructure sentinel from readCountryLockOrThrow: no followedCountriesCountryLocks row exists for the country being followed (logged with breadcrumb before throwing). Country lock rows are seeded alongside shards; a missing lock means seeding is incomplete or the country is outside the seeded set.

Solutions

  1. Run the seed script or cron to create the missing country lock rows
  2. If the country code itself is invalid, INVALID_COUNTRY should fire first — check why an unseeded country reached the lock read
  3. Alert on the country_locks_not_seeded breadcrumb to catch seed drift
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at convex/followedCountries.ts:126 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/4d23fcec38ddf503. Report an issue: GitHub.

Appendix: source

Thrown at convex/followedCountries.ts:126

  await ctx.db.patch(shard._id, { lastTouchedAt: Date.now() });
}

async function readCountryLockOrThrow(
  ctx: MutationCtx,
  country: string,
): Promise<Doc<"followedCountriesCountryLocks">> {
  const lock = await ctx.db
    .query("followedCountriesCountryLocks")
    .withIndex("by_country", (q) => q.eq("country", country))
    .first();
  if (!lock) {
    console.error(
      JSON.stringify({
        breadcrumb: "followed_countries_country_locks_not_seeded",
        country,
      }),
    );
    throw new ConvexError({ kind: "COUNTRY_LOCKS_NOT_SEEDED", country });
  }
  return lock;
}

async function touchCountryLock(
  ctx: MutationCtx,
  lock: Doc<"followedCountriesCountryLocks">,
): Promise<void> {
  await ctx.db.patch(lock._id, { lastTouchedAt: Date.now() });
}

/**
 * Read the per-user serialization row for `userId`. Returns the row (if
 * exists) and the denormalized count (0 if no row). Every mutation that
 * mutates `followedCountries` for the user MUST call this AND patch/insert
 * the row at the end — that read+write pair is what triggers Convex
 * per-document OCC retry under same-user concurrency.
 *

View on GitHub (pinned to eeab0a219f)