garrytan/gstack · error · Error

Unknown catalog mode: ${val}. Use 'trim' (default) or 'full'

Error message

Unknown catalog mode: ${val}. Use 'trim' (default) or 'full'.

What it means

The CATALOG_MODE IIFE in scripts/gen-skill-docs.ts:125 only accepts 'trim' (v1.45 default, shortens frontmatter descriptions and emits proactive-suggestions.json) or 'full' (legacy v1.44 behavior). Any other value, including typos and the old default, throws at startup.

Source

Thrown at scripts/gen-skill-docs.ts:125

  if (!resolved) {
    throw new Error(`Unknown model: ${val}. Use ${ALL_MODEL_NAMES.join(', ')}, or a family variant (e.g., claude-opus-4-7, gpt-5.4-mini, o3).`);
  }
  return resolved;
})();

// ─── Catalog Mode (v1.45.0.0 T4) ────────────────────────────
// 'trim' (default): shorten frontmatter description to lead sentence,
// move routing/voice prose into a "## When to invoke" body section, and
// emit scripts/proactive-suggestions.json (single file across all skills).
// 'full': legacy v1.44 behavior — full description stays in frontmatter.
const CATALOG_MODE_ARG = process.argv.find(a => a.startsWith('--catalog-mode'));
const CATALOG_MODE: 'trim' | 'full' = (() => {
  if (!CATALOG_MODE_ARG) return 'trim';
  const val = CATALOG_MODE_ARG.includes('=')
    ? CATALOG_MODE_ARG.split('=')[1]
    : process.argv[process.argv.indexOf(CATALOG_MODE_ARG) + 1];
  if (val !== 'trim' && val !== 'full') {
    throw new Error(`Unknown catalog mode: ${val}. Use 'trim' (default) or 'full'.`);
  }
  return val;
})();

// ─── Explain-level Overlay ──────────────────────────────────
// --explain-level=terse compresses preamble prose (writing-style, completeness,
// confusion-protocol, context-health) to a single pointer line at gen time.
// Default keeps the runtime-conditional behavior (sections render unconditionally,
// the model skips them when EXPLAIN_LEVEL: terse appears in the preamble echo).
// Opt-in via the build flag so most users get the runtime-flexible default.
const EXPLAIN_LEVEL_ARG = process.argv.find(a => a.startsWith('--explain-level'));
const EXPLAIN_LEVEL: 'default' | 'terse' = (() => {
  if (!EXPLAIN_LEVEL_ARG) return 'default';
  const val = EXPLAIN_LEVEL_ARG.includes('=')
    ? EXPLAIN_LEVEL_ARG.split('=')[1]
    : process.argv[process.argv.indexOf(EXPLAIN_LEVEL_ARG) + 1];
  if (val !== 'default' && val !== 'terse') {
    throw new Error(`Unknown explain level: ${val}. Use 'default' or 'terse'.`);

View on GitHub (pinned to 94993f7401)

Solutions

  1. Omit --catalog-mode entirely to use the 'trim' default
  2. Pass `--catalog-mode=full` only if you intentionally need v1.44 legacy behavior
  3. Spell the value exactly: only lowercase 'trim' or 'full'

Example fix

// before
bun run gen:skill-docs -- --catalog-mode=default
// after
bun run gen:skill-docs -- --catalog-mode=trim
Defensive patterns

Strategy: type-guard

Validate before calling

const VALID_CATALOG = new Set(['trim', 'full']);
const arg = process.argv.find(a => a.startsWith('--catalog-mode'));
const val = arg?.includes('=') ? arg.split('=')[1] : process.argv[process.argv.indexOf(arg!) + 1];
if (val != null && !VALID_CATALOG.has(val)) {
  console.error('--catalog-mode must be one of: trim, full');
  process.exit(2);
}

Type guard

const isCatalogMode = (v: string): v is 'trim' | 'full' => v === 'trim' || v === 'full';

Prevention

When it happens

Trigger: Passing `--catalog-mode=default`, `--catalog-mode legacy`, or a typo like `trım` with non-ASCII characters. CI script still passing `full` after an upgrade without intending legacy behavior.

Common situations: Upgrading gstack and forgetting the default flipped to 'trim'. Copying an old build script that used a different value. Editor autocorrect changing characters.

Related errors


AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12). Data as JSON: /api/errors/f4c2d626832d4d90. Report an issue: GitHub.