DietrichGebert/ponytail · error · Error
description for ${name} must be one line, no quotes, under 1
Error message
description for ${name} must be one line, no quotes, under 160 chars What it means
Thrown by render() in scripts/build-openclaw-skills.js. Before embedding a description into the canonical frontmatter, render() validates the DESCRIPTIONS[name] string: length must be <= 160 chars, it must contain no newline (single line), and it must contain no double-quote character (because the description is emitted wrapped in double quotes as description: "${desc}"). Any violation throws, since a malformed description would produce broken YAML frontmatter in the generated .openclaw skill bundle.
Source
Thrown at scripts/build-openclaw-skills.js:40
'ponytail-audit': 'Audit the whole repo for over-engineering. A ranked list of what to delete, simplify, or replace with stdlib or native features.',
'ponytail-debt': 'Harvest every ponytail: shortcut comment into one debt ledger, so deferrals get tracked instead of forgotten. One-shot report.',
'ponytail-gain': 'Show ponytail measured impact as a scoreboard: less code, less cost, more speed, from the benchmark medians. One-shot display.',
'ponytail-help': "Quick reference for ponytail's modes, skills, and commands. One-shot display.",
};
const NAMES = Object.keys(DESCRIPTIONS);
function sourceBody(name) {
const src = fs.readFileSync(path.join(ROOT, 'skills', name, 'SKILL.md'), 'utf8').replace(/\r\n/g, '\n');
const fm = src.match(/^---\n[\s\S]*?\n---\n?/);
if (!fm) throw new Error(`skills/${name}/SKILL.md has no frontmatter`);
return src.slice(fm[0].length);
}
function render(name) {
const desc = DESCRIPTIONS[name];
if (desc.length > 160 || desc.includes('\n') || desc.includes('"')) {
throw new Error(`description for ${name} must be one line, no quotes, under 160 chars`);
}
const frontmatter =
`---\nname: ${name}\ndescription: "${desc}"\nhomepage: ${HOMEPAGE}\nlicense: MIT\n---\n`;
return frontmatter + sourceBody(name);
}
function outPath(name) {
return path.join(ROOT, '.openclaw', 'skills', name, 'SKILL.md');
}
module.exports = { DESCRIPTIONS, NAMES, render, outPath, sourceBody };
if (require.main === module) {
for (const name of NAMES) {
const p = outPath(name);
fs.mkdirSync(path.dirname(p), { recursive: true });
fs.writeFileSync(p, render(name));
console.log('wrote', path.relative(ROOT, p).replace(/\\/g, '/'));View on GitHub (pinned to 2ed6c52c9d)
Solutions
- Shorten the offending DESCRIPTIONS[name] value to <= 160 characters on a single line with no double quotes.
- Replace any double quotes in the description with single quotes or backticks; remove literal newlines.
- Re-run node scripts/build-openclaw-skills.js and confirm render() passes for that skill.
Example fix
// before — scripts/build-openclaw-skills.js 'ponytail-audit': 'Audit the whole repo for over-engineering. A ranked list of what to delete, simplify, or replace with stdlib or native features. "Quick" one-shot report.', // after — single line, <= 160 chars, no double quotes 'ponytail-audit': 'Audit the whole repo for over-engineering. A ranked list of what to delete, simplify, or replace with stdlib or native features. One-shot report.',
Defensive patterns
Strategy: validation
Validate before calling
// Validate the whole DESCRIPTIONS map at module load, before build runs
function validDescription(d) {
return typeof d === 'string' && d.length <= 160 && !d.includes('\n') && !d.includes('"');
}
for (const [name, desc] of Object.entries(DESCRIPTIONS)) {
if (!validDescription(desc)) {
throw new Error(`${name}: description must be one line, no double quotes, <= 160 chars (got ${desc.length})`);
}
} Type guard
function isValidDescription(d) {
return typeof d === 'string' && d.length > 0 && d.length <= 160 && !d.includes('\n') && !d.includes('"');
} Try / catch
try {
render(name);
} catch (e) {
if (/must be one line/.test(e.message)) {
console.error(`Fix DESCRIPTIONS['${name}']: <= 160 chars, single line, no double quotes.`);
}
throw e;
} Prevention
- Enforce the 160-char / single-line / no-quote rule with an editor lint or a unit test on the DESCRIPTIONS map.
- When adding a skill, write the description first and run render(name) in isolation before committing.
- Avoid pasting prose that may carry smart/curly double quotes; retype quotes as ASCII single quotes.
When it happens
Trigger: Editing the DESCRIPTIONS object in scripts/build-openclaw-skills.js and adding/altering an entry whose value exceeds 160 characters, spans multiple lines (contains '\n'), or contains a '"' character. Then running node scripts/build-openclaw-skills.js, which iterates NAMES and calls render() on each.
Common situations: A new ponytail skill is added with a verbose one-liner that crosses the 160-char openclaw/skill-registry limit. A description is copy-pasted from prose containing a smart/curly double quote or an actual ASCII double quote. A contributor formats a description across two lines for readability in the source, introducing a literal newline.
Related errors
AI-assisted analysis of DietrichGebert/ponytail@2ed6c52c9d (2026-08-12).
Data as JSON: /api/errors/d1dd1f707e598765.
Report an issue: GitHub.