pbakaus/impeccable · error · Error
concept-seed: no local catalog (set IMPECCABLE_CATALOG_DIR o
Error message
concept-seed: no local catalog (set IMPECCABLE_CATALOG_DIR or pass sourceConcepts)
What it means
Thrown by requireLocalConcepts when loadLocal() returned null, meaning no valid local concept catalog could be loaded. The skill resolves concepts from a local catalog first (the private service repo, evals, and tests point IMPECCABLE_CATALOG_DIR at one), then the roll API, then a degraded assignment-only seed — but requireLocalConcepts demands the local path. The full catalog intentionally does not ship with the skill.
Source
Thrown at skill/scripts/concept-seed.mjs:157
const compositionState = readCompositionCatalog(
join(catalogDir, 'composition-ingredients.json'),
join(catalogDir, 'composition-reviews.json')
);
localState = {
concepts: catalogState.concepts,
compositions: compositionState.compositions,
};
} catch {
localState = null;
}
localStates.set(catalogDir, localState);
return localState;
}
function requireLocalConcepts() {
const local = loadLocal();
if (!local) {
throw new Error('concept-seed: no local catalog (set IMPECCABLE_CATALOG_DIR or pass sourceConcepts)');
}
return local;
}
async function fetchRoll({ scope, key, mode, grain, platform, reroll }) {
const params = new URLSearchParams({ scope, key, reroll: String(reroll) });
if (mode) params.set('mode', mode);
if (grain) params.set('grain', grain);
if (platform) params.set('platform', platform);
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), apiBudgetMs());
try {
// Race the budget explicitly: abort signals do not reliably cancel the
// TCP connect phase, so a blackholed route would otherwise stall ~10s.
const response = await Promise.race([
fetch(`${API_BASE}/roll?${params}`, { signal: controller.signal }),
new Promise(resolveTimeout => setTimeout(() => resolveTimeout(null), apiBudgetMs())),
]);View on GitHub (pinned to d14711ae3d)
Solutions
- Set IMPECCABLE_CATALOG_DIR to a directory containing valid concept-ingredients.json + concept-reviews.json.
- If you are calling seedConcepts programmatically, pass sourceConcepts directly to bypass the local-catalog requirement.
- Verify the catalog files exist and pass validation (validateConceptCatalog) at that path.
- If you only have API access, use the fetchRoll path instead of requireLocalConcepts.
Example fix
// before
process.env.IMPECCABLE_CATALOG_DIR; // undefined -> throws [83]
const local = requireLocalConcepts();
// after: point at a real catalog, or supply concepts inline
process.env.IMPECCABLE_CATALOG_DIR = '/path/to/private/catalog';
// or, programmatically:
const seeded = await seedConcepts({ sourceConcepts: myConcepts, scope: 'surface' }); Defensive patterns
Strategy: validation
Validate before calling
// Verify a usable local catalog exists before calling requireLocalConcepts.
import { existsSync } from 'node:fs';
import { join } from 'node:path';
function hasLocalCatalog(dir = process.env.IMPECCABLE_CATALOG_DIR) {
if (!dir) return false;
return existsSync(join(dir, 'concept-ingredients.json'))
&& existsSync(join(dir, 'concept-reviews.json'));
} Prevention
- Set IMPECCABLE_CATALOG_DIR in CI/eval environments that need the local path.
- When calling seedConcepts programmatically, pass sourceConcepts to avoid the local-catalog dependency entirely.
- If you only have network access, use the fetchRoll path instead of requireLocalConcepts.
When it happens
Trigger: IMPECCABLE_CATALOG_DIR is unset and the script directory has no catalog files; the env var points at an empty or non-existent directory; the catalog files exist but failed validation (see [82]); a fresh public checkout where the private catalog is absent.
Common situations: Running concept-seed in a plain skill install (no private catalog); a CI job that forgot to set IMPECCABLE_CATALOG_DIR; pointing the env var at a stale checkout; catalog JSON corrupted after a bad merge.
Related errors
- concept-seed: no local catalog (set IMPECCABLE_CATALOG_DIR o
- invalid catalog: ${validation.errors.join('; ')}
- No live copy-edit AI runner is available.
- concept-seed: --scope must be direction or surface
- concept-seed: --reroll must be a non-negative integer
AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13).
Data as JSON: /api/errors/ebe0990d01ac9cf3.
Report an issue: GitHub.