{"record":{"id":"f5e700a4f7c4f4a2","repo":"koala73/worldmonitor","slug":"shards-not-seeded","errorCode":"SHARDS_NOT_SEEDED","errorMessage":"SHARDS_NOT_SEEDED","messagePattern":"SHARDS_NOT_SEEDED","errorType":"error_code","errorClass":"ConvexError","httpStatus":null,"severity":"error","filePath":"convex/followedCountries.ts","lineNumber":93,"sourceCode":"  ctx: MutationCtx,\n  userId: string,\n): Promise<Doc<\"followedCountriesShards\">> {\n  const shardId = userIdToShard(userId);\n  const shard = await ctx.db\n    .query(\"followedCountriesShards\")\n    .withIndex(\"by_shard\", (q) => q.eq(\"shardId\", shardId))\n    .first();\n  if (!shard) {\n    // Operator error — should never happen in production after deploy +\n    // the daily `_seedShards` cron. Logged loudly so on-call sees it.\n    console.error(\n      JSON.stringify({\n        breadcrumb: \"followed_countries_shards_not_seeded\",\n        shardId,\n        shardCount: SHARD_COUNT,\n      }),\n    );\n    throw new ConvexError({ kind: \"SHARDS_NOT_SEEDED\", shardId });\n  }\n  return shard;\n}\n\n/**\n * Patch the shard row's `lastTouchedAt` — the OCC-serializing write that\n * pairs with `readShardOrThrow`. MUST run on the success path AFTER all\n * other writes; on any throw, Convex aborts the entire transaction and\n * the patch is rolled back along with everything else.\n */\nasync function touchShard(\n  ctx: MutationCtx,\n  shard: Doc<\"followedCountriesShards\">,\n): Promise<void> {\n  await ctx.db.patch(shard._id, { lastTouchedAt: Date.now() });\n}\n\nasync function readCountryLockOrThrow(","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/koala73/worldmonitor/blob/eeab0a219fce0f02a00603b532dbae9041b934ac/convex/followedCountries.ts#L75-L111","documentation":"Infrastructure sentinel from readShardOrThrow: no followedCountriesShards row exists for the user's shard (userIdToShard). Shards are pre-created by deploy seeding plus the daily _seedShards cron, so hitting this is an operator or deployment error — it is logged loudly (breadcrumb JSON) for on-call before throwing.","triggerScenarios":"Thrown at convex/followedCountries.ts:93 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Run the shard-seed script or the _seedShards cron to create the missing shard rows","Verify SHARD_COUNT matches between seeding and lookup — a mismatch makes some shards permanently missing","Alert on the followed_countries_shards_not_seeded breadcrumb so on-call catches seed drift early"],"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"}