{"record":{"id":"83612eff4fcf0dc0","repo":"can1357/oh-my-pi","slug":"managed-skill-name-does-not-exist-use-action","errorCode":null,"errorMessage":"Managed skill \"${name}\" does not exist. Use action \"create\" to add it.","messagePattern":"Managed skill \"(.+?)\" does not exist\\. Use action \"create\" to add it\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/autolearn/managed-skills.ts","lineNumber":213,"sourceCode":"\t\t\t\tawait fs.writeFile(file, content, { flag: \"wx\" });\n\t\t\t} catch (err) {\n\t\t\t\tif ((err as { code?: string }).code === \"EEXIST\") {\n\t\t\t\t\tthrow new Error(`Managed skill \"${name}\" already exists. Use action \"update\" to change it.`);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t\treturn { path: file };\n\t\t}\n\t\t// update: the file must already exist, be a plain managed file, and must\n\t\t// not share an inode with a user-authored file via hard link. Open the\n\t\t// checked file handle before truncating so a path swap after lstat cannot\n\t\t// redirect the write into a symlink or newly hard-linked target.\n\t\tconst fileStat = await fs.lstat(file).catch(err => {\n\t\t\tif (isEnoent(err)) return null;\n\t\t\tthrow err;\n\t\t});\n\t\tif (fileStat === null) {\n\t\t\tthrow new Error(`Managed skill \"${name}\" does not exist. Use action \"create\" to add it.`);\n\t\t}\n\t\tif (fileStat.isSymbolicLink()) {\n\t\t\tthrow new Error(`Managed skill \"${name}\" SKILL.md is a symlink; refusing to overwrite it.`);\n\t\t}\n\t\tassertManagedSkillFileSafeForUpdate(name, fileStat);\n\t\tconst handle = await openManagedSkillFileForUpdate(name, file);\n\t\ttry {\n\t\t\tconst openStat = await handle.stat();\n\t\t\tassertManagedSkillFileSafeForUpdate(name, openStat);\n\t\t\tawait handle.truncate(0);\n\t\t\tawait handle.writeFile(content);\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t\treturn { path: file };\n\t});\n}\n","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/autolearn/managed-skills.ts#L195-L231","documentation":"writeManagedSkill with action \"update\" requires the managed SKILL.md to already exist; lstat returning null (ENOENT) produces this error. It prevents update from silently creating files, keeping create/update semantics strict and symmetric with error 700.","triggerScenarios":"Calling writeManagedSkill({ action: \"update\", name, ... }) when ~/.omp/agent/managed-skills/<name>/SKILL.md does not exist — the skill was deleted, never created, or the name is misspelled.","commonSituations":"An agent tries to enhance a skill that was pruned between sessions; a typo in the skill name; code assumed a prior create succeeded but it failed.","solutions":["Call writeManagedSkill with action \"create\" to add the missing skill.","Verify the exact skill name (lowercase letters/digits/hyphens) matches the directory on disk.","Check that the managed-skills directory is the one being inspected (~/.omp/agent/managed-skills, not the authored skills dir)."],"exampleFix":"// before\nawait writeManagedSkill({ action: \"update\", name: \"my-skill\", description: \"d\", body: \"b\" });\n// after\nconst file = `${getManagedSkillsDir()}/my-skill/SKILL.md`;\nconst exists = await Bun.file(file).exists();\nawait writeManagedSkill({ action: exists ? \"update\" : \"create\", name: \"my-skill\", description: \"d\", body: \"b\" });","handlingStrategy":"validation","validationCode":"const file = `${getManagedSkillsDir()}/${sanitizeSkillName(name)}/SKILL.md`;\nconst exists = await fs.lstat(file).then(() => true).catch(e => { if (isEnoent(e)) return false; throw e; });\nif (!exists) throw new Error(`refusing to update missing skill ${name}`);","typeGuard":null,"tryCatchPattern":"try {\n  await writeManagedSkill({ action: \"update\", name, description, body });\n} catch (err) {\n  if (err instanceof Error && err.message.includes('does not exist')) {\n    await writeManagedSkill({ action: \"create\", name, description, body });\n  } else throw err;\n}","preventionTips":["List the managed-skills directory before mutating and match names exactly.","Sanitize the name first so case/whitespace mismatches don't cause phantom 'missing' skills.","Handle deletion events (user removed the skill) before issuing update."],"tags":["filesystem","missing-resource"],"backgroundTag":"file-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}