{"record":{"id":"4d23fcec38ddf503","repo":"koala73/worldmonitor","slug":"country-locks-not-seeded","errorCode":"COUNTRY_LOCKS_NOT_SEEDED","errorMessage":"COUNTRY_LOCKS_NOT_SEEDED","messagePattern":"COUNTRY_LOCKS_NOT_SEEDED","errorType":"error_code","errorClass":"ConvexError","httpStatus":null,"severity":"error","filePath":"convex/followedCountries.ts","lineNumber":126,"sourceCode":"  await ctx.db.patch(shard._id, { lastTouchedAt: Date.now() });\n}\n\nasync function readCountryLockOrThrow(\n  ctx: MutationCtx,\n  country: string,\n): Promise<Doc<\"followedCountriesCountryLocks\">> {\n  const lock = await ctx.db\n    .query(\"followedCountriesCountryLocks\")\n    .withIndex(\"by_country\", (q) => q.eq(\"country\", country))\n    .first();\n  if (!lock) {\n    console.error(\n      JSON.stringify({\n        breadcrumb: \"followed_countries_country_locks_not_seeded\",\n        country,\n      }),\n    );\n    throw new ConvexError({ kind: \"COUNTRY_LOCKS_NOT_SEEDED\", country });\n  }\n  return lock;\n}\n\nasync function touchCountryLock(\n  ctx: MutationCtx,\n  lock: Doc<\"followedCountriesCountryLocks\">,\n): Promise<void> {\n  await ctx.db.patch(lock._id, { lastTouchedAt: Date.now() });\n}\n\n/**\n * Read the per-user serialization row for `userId`. Returns the row (if\n * exists) and the denormalized count (0 if no row). Every mutation that\n * mutates `followedCountries` for the user MUST call this AND patch/insert\n * the row at the end — that read+write pair is what triggers Convex\n * per-document OCC retry under same-user concurrency.\n *","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/koala73/worldmonitor/blob/eeab0a219fce0f02a00603b532dbae9041b934ac/convex/followedCountries.ts#L108-L144","documentation":"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.","triggerScenarios":"Thrown at convex/followedCountries.ts:126 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Run the seed script or cron to create the missing country lock rows","If the country code itself is invalid, INVALID_COUNTRY should fire first — check why an unseeded country reached the lock read","Alert on the country_locks_not_seeded breadcrumb to catch seed drift"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"eeab0a219fce0f02a00603b532dbae9041b934ac","analyzedAt":"2026-08-21T16:51:25.751Z","contentChangedAt":"2026-08-21T16:51:25.751Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}