garrytan/gstack · error · Error

${hostConfig.displayName} description for "${name}" is ${des

Error message

${hostConfig.displayName} description for "${name}" is ${description.length} chars (max ${fm.descriptionLimit}). Compress the description in the .tmpl file.

What it means

Host-specific frontmatter description length limit exceeded. When frontmatter.descriptionLimit is set and descriptionLimitBehavior === 'error' (the default), the generator throws rather than producing oversized frontmatter. The limit comes from the host config (fm.descriptionLimit) and the offending skill name + lengths are included.

Source

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

    }
    return content;
  }

  // Allowlist mode: reconstruct frontmatter with only allowed fields
  const fmStart = content.indexOf('---\n');
  if (fmStart !== 0) return content;
  const fmEnd = content.indexOf('\n---', fmStart + 4);
  if (fmEnd === -1) return content;
  const frontmatter = content.slice(fmStart + 4, fmEnd);
  const body = content.slice(fmEnd + 4);
  const { name, description } = extractNameAndDescription(content);

  // Description limit enforcement
  if (fm.descriptionLimit) {
    const behavior = fm.descriptionLimitBehavior || 'error';
    if (description.length > fm.descriptionLimit) {
      if (behavior === 'error') {
        throw new Error(
          `${hostConfig.displayName} description for "${name}" is ${description.length} chars (max ${fm.descriptionLimit}). ` +
          `Compress the description in the .tmpl file.`
        );
      } else if (behavior === 'warn') {
        console.warn(`WARNING: ${hostConfig.displayName} description for "${name}" exceeds ${fm.descriptionLimit} chars`);
      }
      // 'truncate' — silently proceed
    }
  }

  // Build frontmatter with allowed fields
  const indentedDesc = description.split('\n').map(l => `  ${l}`).join('\n');
  let newFm = `---\nname: ${name}\ndescription: |\n${indentedDesc}\n`;

  // Add extra fields (host-wide)
  if (fm.extraFields) {
    for (const [key, value] of Object.entries(fm.extraFields)) {
      if (key !== 'name' && key !== 'description') {

View on GitHub (pinned to 94993f7401)

Solutions

  1. Compress the description in the .tmpl file to one lead sentence
  2. Move routing/voice detail into a body `## When to invoke` section (catalog-mode=trim does this automatically)
  3. If the longer description is intentional and supported, set descriptionLimitBehavior: 'warn' for that host
  4. Split the skill into smaller, focused skills
Defensive patterns

Strategy: validation

Validate before calling

import { readFileSync } from 'fs';
const content = readFileSync(tmplPath, 'utf-8');
const desc = extractNameAndDescription(content).description;
if (fm.descriptionLimit && desc.length > fm.descriptionLimit && (fm.descriptionLimitBehavior || 'error') === 'error') {
  console.error(`Description for ${tmplPath} is ${desc.length} chars (max ${fm.descriptionLimit}); trim before building`);
  process.exit(2);
}

Prevention

When it happens

Trigger: Adding prose to a .tmpl description that pushes over the host's limit (e.g. Codex caps at 1024). Generating for a host with a tighter limit than tested locally. descriptionLimitBehavior set to 'error' on a verbose skill.

Common situations: Editing a .tmpl description to add a use case. Multi-host build where one host's limit is stricter. Accumulating description bloat across versions.

Related errors


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