Yeachan-Heo/oh-my-codex · error · Error
${filePath} frontmatter "${key}" has an unterminated quoted
Error message
${filePath} frontmatter "${key}" has an unterminated quoted string What it means
A frontmatter value starting with a quote must end with the same quote after at least 2 characters. This error fires for unterminated quoted strings, e.g. "my-skill (missing closing quote).
Source
Thrown at src/cli/setup.ts:2226
function parseSkillFrontmatterScalar(
value: string,
key: string,
filePath: string,
): string {
const trimmed = value.trim();
if (!trimmed) {
throw new Error(`${filePath} frontmatter "${key}" must not be empty`);
}
if (trimmed === "|" || trimmed === ">") {
throw new Error(
`${filePath} frontmatter "${key}" must be a single-line string`,
);
}
const quote = trimmed[0];
if (quote === '"' || quote === "'") {
if (trimmed.length < 2 || trimmed.at(-1) !== quote) {
throw new Error(
`${filePath} frontmatter "${key}" has an unterminated quoted string`,
);
}
const unquoted = trimmed.slice(1, -1).trim();
if (!unquoted) {
throw new Error(`${filePath} frontmatter "${key}" must not be empty`);
}
return unquoted;
}
const unquoted = trimmed.replace(/\s+#.*$/, "").trim();
if (!unquoted) {
throw new Error(`${filePath} frontmatter "${key}" must not be empty`);
}
return unquoted;
}
export function parseSkillFrontmatter(View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Close the quoted string: name: "my-skill"
- If the leading character is not meant as a quote (e.g. it's), rephrase or wrap the whole value in matched quotes
- Avoid smart/curly quotes; use plain ASCII quotes
Example fix
# before name: "my-skill # after name: "my-skill"
Defensive patterns
Strategy: validation
Validate before calling
const line = 'name: "my-skill';
const v = line.replace(/^[^:]*:\s*/, "").trim();
const q = v[0];
const terminated = !(q === '"' || q === "'") || (v.length >= 2 && v.at(-1) === q);
if (!terminated) throw new Error("unterminated quoted frontmatter value"); Type guard
const isTerminatedQuoted = (v: string): boolean => {
const q = v.trim()[0];
if (q !== '"' && q !== "'") return true;
const t = v.trim();
return t.length >= 2 && t.at(-1) === q;
}; Try / catch
try { parseSkillFrontmatter(content); } catch (e) { if (e instanceof Error && e.message.includes("unterminated quoted string")) { /* add the matching closing quote on the flagged key */ } else throw e; } Prevention
- Always close quotes in pairs
- Avoid leading apostrophes in unquoted values
- Use plain ASCII quotes, not smart quotes
When it happens
Trigger: Values like 'name: "my-skill' or 'description: it's fine' where an opening double/single quote is not matched by a closing one at the end of the trimmed value.
Common situations: Apostrophes at the start of descriptions, smart quotes pasted from word processors, or simply forgetting the closing quote.
Understand the failure class
Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.
Related errors
- ${filePath} frontmatter "${key}" must not be empty
- ${filePath} frontmatter "${key}" must be a single-line strin
- ${filePath} is missing a non-empty frontmatter "name"
- ${filePath} is missing a non-empty frontmatter "description"
- ${filePath} must start with YAML frontmatter containing non-
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/b3d184570f03f875.
Report an issue: GitHub.