Yeachan-Heo/oh-my-codex · error · Error

${filePath} must start with YAML frontmatter containing non-

Error message

${filePath} must start with YAML frontmatter containing non-empty name and description fields

What it means

parseSkillFrontmatter requires the file to begin with a '---' delimited YAML frontmatter block containing at least name and description. If the regex /^---\r?\n([\s\S]*?)\r?\n---/ does not match, the file is rejected before any field parsing.

Source

Thrown at src/cli/setup.ts:2252

		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(
	content: string,
	filePath = "SKILL.md",
): SkillFrontmatterMetadata {
	const frontmatterMatch = content.match(
		/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/,
	);
	if (!frontmatterMatch) {
		throw new Error(
			`${filePath} must start with YAML frontmatter containing non-empty name and description fields`,
		);
	}

	let name: string | undefined;
	let description: string | undefined;
	const lines = frontmatterMatch[1].split(/\r?\n/);

	for (const [index, rawLine] of lines.entries()) {
		const line = rawLine.trimEnd();
		const trimmed = line.trim();
		if (!trimmed || trimmed.startsWith("#")) continue;
		if (/^\s/.test(rawLine)) continue;

		const match = line.match(/^([A-Za-z0-9_-]+):(.*)$/);
		if (!match) {
			throw new Error(
				`${filePath} has invalid YAML frontmatter on line ${index + 2}: ${trimmed}`,

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Start the file with '---' on line 1, add the fields, close with a second '---'
  2. Ensure both fences begin at column 0 with no leading whitespace
  3. Include non-empty name and description fields inside the block
  4. Normalize line endings (CRLF is tolerated, stray BOM is not — remove BOM)

Example fix

# before
# My Skill
Does things.
# after
---
name: my-skill
description: Does things.
---
# My Skill
Does things.
Defensive patterns

Strategy: validation

Validate before calling

const hasFences = content.startsWith("---") && /^---\r?\n[\s\S]*?\r?\n---/.test(content);
if (!hasFences) throw new Error("missing or misplaced frontmatter fences");

Type guard

const startsWithFrontmatter = (c: string): boolean =>
  /^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/.test(c);

Try / catch

try { parseSkillFrontmatter(content); } catch (e) { if (e instanceof Error && e.message.includes("must start with YAML frontmatter")) { /* add --- fences at column 0 with name and description */ } else throw e; }

Prevention

When it happens

Trigger: SKILL.md missing the opening '---' fence, having text before it, using '···' or other delimiters, or missing the closing fence so the block never terminates.

Common situations: Writing a plain markdown file and forgetting frontmatter entirely, Windows line-ending mixups, or fences indented by spaces (must start at column 0).

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


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/1b2fee9dd7cd9708. Report an issue: GitHub.