Description
When a skill's SKILL.md frontmatter has a numeric-only name field (e.g., name: 12306), the YAML parser (js-yaml) interprets it as a number instead of a string. This causes ALL slash commands (not just the affected skill) to fail with:
cmd.name.toLowerCase is not a function. (In 'cmd.name.toLowerCase()', 'cmd.name.toLowerCase' is undefined)
Root Cause
-
loadSkillFromPath() (line ~88906) uses data.name directly from YAML frontmatter without type conversion:
const baseName = data.name || options.defaultName;
-
When the YAML field is name: 12306, js-yaml parses it as integer 12306 (number type), not string "12306".
-
This number flows through skillToCommandInfo() → discoverAllCommands() → into the command list.
-
When ANY slash command is invoked, findCommand2() (line ~94715) iterates all commands and crashes:
allCommands.find((cmd) => cmd.name.toLowerCase() === commandName.toLowerCase())
Numbers don't have .toLowerCase(), so it throws.
Impact
- All slash commands break, not just the offending skill's command
- The error message is confusing — doesn't indicate which skill caused the problem
- No graceful degradation; the entire command lookup fails
Reproduction
- Create a skill with a numeric-only name in frontmatter:
---
name: 12306
description: Some skill
---
- Place it in
~/.claude/skills/12306/SKILL.md
- Restart OpenCode
- Try any slash command (e.g.,
/handoff)
- Observe: "Failed to send command" / "Request failed"
Suggested Fix
Add type coercion in loadSkillFromPath():
// Line ~88906
const baseName = String(data.name || options.defaultName);
Or add a defensive check in findCommand2():
allCommands.find((cmd) => typeof cmd.name === "string" && cmd.name.toLowerCase() === commandName.toLowerCase())
Ideally both, for defense in depth.
Environment
- oh-my-opencode: 3.16.0
- OpenCode: 1.4.1
- Platform: Linux x64
Description
When a skill's
SKILL.mdfrontmatter has a numeric-onlynamefield (e.g.,name: 12306), the YAML parser (js-yaml) interprets it as a number instead of a string. This causes ALL slash commands (not just the affected skill) to fail with:Root Cause
loadSkillFromPath()(line ~88906) usesdata.namedirectly from YAML frontmatter without type conversion:When the YAML field is
name: 12306,js-yamlparses it as integer12306(number type), not string"12306".This number flows through
skillToCommandInfo()→discoverAllCommands()→ into the command list.When ANY slash command is invoked,
findCommand2()(line ~94715) iterates all commands and crashes:Numbers don't have
.toLowerCase(), so it throws.Impact
Reproduction
~/.claude/skills/12306/SKILL.md/handoff)Suggested Fix
Add type coercion in
loadSkillFromPath():Or add a defensive check in
findCommand2():Ideally both, for defense in depth.
Environment