can1357/oh-my-pi · error
Invalid skill name "${raw}". Use lowercase letters, digits,
Error message
Invalid skill name "${raw}". Use lowercase letters, digits, and hyphens (1-64 chars, starting with a letter or digit). What it means
sanitizeSkillName validates a managed-skill name against ^[a-z0-9][a-z0-9-]{0,63}$ after trimming and lowercasing. Names outside this strict allowlist are rejected because a bad name could escape getManagedSkillsDir() (path traversal via .. or slashes).
Source
Thrown at packages/coding-agent/src/autolearn/managed-skills.ts:37
/** Hard cap on a managed SKILL.md body to keep generated skills bounded. */
export const MAX_MANAGED_SKILL_BYTES = 64_000;
const SKILL_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
/** Resolve the isolated managed-skills directory (`~/.omp/agent/managed-skills`). */
export function getManagedSkillsDir(agentDir: string = getAgentDir()): string {
return path.join(agentDir, "managed-skills");
}
/**
* Validate + normalize a managed-skill name. Throws on anything outside the
* strict allowlist so a bad name can never escape `getManagedSkillsDir()`
* (blocks `..`, slashes, empty, and uppercase).
*/
export function sanitizeSkillName(raw: string): string {
const name = raw.trim().toLowerCase();
if (!SKILL_NAME_PATTERN.test(name)) {
throw new Error(
`Invalid skill name "${raw}". Use lowercase letters, digits, and hyphens (1-64 chars, starting with a letter or digit).`,
);
}
return name;
}
/**
* Whether `name` is a safe managed-skill name (the exact post-sanitize shape).
* Used to validate names read from disk at discovery time — a managed
* `SKILL.md` whose `frontmatter.name` was not produced by `sanitizeSkillName`
* (e.g. hand-placed) must not render unescaped into the system prompt.
*/
export function isValidManagedSkillName(name: string): boolean {
return SKILL_NAME_PATTERN.test(name);
}
/**
* Neutralize a machine-generated managed-skill description so it cannot breakView on GitHub (pinned to 9690622007)
Solutions
- Slugify the input before calling: trim, lowercase, replace non [a-z0-9] runs with '-', trim leading/trailing hyphens, cap at 64 chars
- Validate the name with isValidManagedSkillName before calling the API
- Ensure the name starts with a letter or digit (a leading '-' is invalid)
- Check the failing name in the message for hidden characters like slashes or dots
Example fix
// before
writeManagedSkill({ name: taskTitle, ... });
// after
const name = taskTitle.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 64) || 'skill';
writeManagedSkill({ name, ... }); Defensive patterns
Strategy: validation
Validate before calling
const SKILL_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
if (!SKILL_NAME_PATTERN.test(raw.trim().toLowerCase())) {
throw new Error(`invalid skill name: ${raw}`);
} Type guard
function isValidManagedSkillName(name: string): boolean {
return /^[a-z0-9][a-z0-9-]{0,63}$/.test(name);
} Try / catch
let name: string;
try {
name = sanitizeSkillName(raw);
} catch {
name = slugify(raw); // lowercase, [^a-z0-9]+ -> '-', trim '-', slice(0,64)
} Prevention
- Slugify any user- or LLM-derived title before using it as a skill name
- Validate with isValidManagedSkillName before calling write/delete APIs
- Never pass path segments, spaces, or punctuation as skill names
- Cap names at 64 characters and ensure they start with a letter or digit
When it happens
Trigger: Calling writeManagedSkill or any API that resolves a skill name (name/safe getters) with a raw string containing uppercase, slashes, '..', spaces, symbols, an empty string, or more than 64 characters that still fails the pattern after trim/lowercase.
Common situations: Auto-learn generates a skill title with spaces or punctuation; a user-facing label (e.g. 'Fix Build Errors!') is passed as the name instead of a slug; a name containing a path segment from user input.
Related errors
- Unknown tool${unknown.length === 1 ? "" : "s"} in --tools: $
- Unknown OAuth provider '${providerArg}'. Known: ${providers
- Invalid marketplace plugin package name: ${JSON.stringify(na
- Invalid plugin name: "${name}"
- Invalid marketplace name: "${marketplace}"
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/3edef6d93e9cabab.
Report an issue: GitHub.