{"record":{"id":"b5319bfe187e315f","repo":"pbakaus/impeccable","slug":"concept-seed-no-local-catalog-set-impeccable-cat","errorCode":null,"errorMessage":"concept-seed: no local catalog (set IMPECCABLE_CATALOG_DIR or pass sourceConcepts)","messagePattern":"concept-seed: no local catalog \\(set IMPECCABLE_CATALOG_DIR or pass sourceConcepts\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/skills/impeccable/scripts/concept-seed.mjs","lineNumber":157,"sourceCode":"    const compositionState = readCompositionCatalog(\n      join(catalogDir, 'composition-ingredients.json'),\n      join(catalogDir, 'composition-reviews.json')\n    );\n    localState = {\n      concepts: catalogState.concepts,\n      compositions: compositionState.compositions,\n    };\n  } catch {\n    localState = null;\n  }\n  localStates.set(catalogDir, localState);\n  return localState;\n}\n\nfunction requireLocalConcepts() {\n  const local = loadLocal();\n  if (!local) {\n    throw new Error('concept-seed: no local catalog (set IMPECCABLE_CATALOG_DIR or pass sourceConcepts)');\n  }\n  return local;\n}\n\nasync function fetchRoll({ scope, key, mode, grain, platform, reroll }) {\n  const params = new URLSearchParams({ scope, key, reroll: String(reroll) });\n  if (mode) params.set('mode', mode);\n  if (grain) params.set('grain', grain);\n  if (platform) params.set('platform', platform);\n  const controller = new AbortController();\n  const timer = setTimeout(() => controller.abort(), apiBudgetMs());\n  try {\n    // Race the budget explicitly: abort signals do not reliably cancel the\n    // TCP connect phase, so a blackholed route would otherwise stall ~10s.\n    const response = await Promise.race([\n      fetch(`${API_BASE}/roll?${params}`, { signal: controller.signal }),\n      new Promise(resolveTimeout => setTimeout(() => resolveTimeout(null), apiBudgetMs())),\n    ]);","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/pbakaus/impeccable/blob/d14711ae3d1a1dd62dee61a358d27f107c51ccd0/plugin/skills/impeccable/scripts/concept-seed.mjs#L139-L175","documentation":"Thrown by requireLocalConcepts() when loadLocal() returned null — meaning no usable local catalog was found at IMPECCABLE_CATALOG_DIR (directory missing, files missing, or catalog validation failed and was swallowed). The caller asked for the local catalog explicitly, so rather than silently falling through to the roll API it surfaces the requirement.","triggerScenarios":"Calling a code path that uses requireLocalConcepts() (e.g. --sourceConcepts=local or a mode that must read the private catalog) when IMPECCABLE_CATALOG_DIR is unset, points at a non-existent directory, or holds catalog JSON that failed validation (see error [3]).","commonSituations":"Running the seeder outside the private service repo without IMPECCABLE_CATALOG_DIR set; the catalog directory was moved; a catalog schema change made the local files invalid.","solutions":["Set IMPECCABLE_CATALOG_DIR to a directory holding valid concept-ingredients.json / concept-reviews.json (and the composition equivalents).","If you do not have the private catalog, pass sourceConcepts explicitly or use a mode that falls through to the roll API instead of requiring local.","If the directory is set but still null, validate the catalog JSON (see error [3]) to find the schema violation."],"exampleFix":"# before\n$ node concept-seed.mjs --sourceConcepts local ...\n# throws: no local catalog\n\n# after\n$ IMPECCABLE_CATALOG_DIR=/path/to/catalog node concept-seed.mjs --sourceConcepts local ...","handlingStrategy":"validation","validationCode":"const local = loadLocal(process.env.IMPECCABLE_CATALOG_DIR || CATALOG_DIR);\nif (!local) {\n  throw new Error('Set IMPECCABLE_CATALOG_DIR to a valid catalog directory before using local concepts.');\n}","typeGuard":"function localCatalogAvailable(catalogDir) {\n  return loadLocal(catalogDir) !== null;\n}","tryCatchPattern":"try {\n  requireLocalConcepts();\n} catch (err) {\n  if (/no local catalog/.test(err.message)) {\n    console.error('No local catalog; set IMPECCABLE_CATALOG_DIR or use a non-local source.');\n  } else throw err;\n}","preventionTips":["Set IMPECCABLE_CATALOG_DIR in any environment that requires the private catalog.","Validate the catalog directory contents at startup, not only on first use.","Offer a non-local fallback explicitly so users do not hit requireLocalConcepts unguarded."],"tags":["concept-seed","catalog","config","env","missing-data"],"backgroundTag":null,"analyzedSha":"d14711ae3d1a1dd62dee61a358d27f107c51ccd0","analyzedAt":"2026-08-13T00:52:25.771Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}