{"record":{"id":"af8f11737b0b49a3","repo":"can1357/oh-my-pi","slug":"managed-skill-name-skill-md-is-not-a-regular","errorCode":null,"errorMessage":"Managed skill \"${name}\" SKILL.md is not a regular file; refusing to overwrite it.","messagePattern":"Managed skill \"(.+?)\" SKILL\\.md is not a regular file; refusing to overwrite it\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/autolearn/managed-skills.ts","lineNumber":131,"sourceCode":" * follows intermediate components, so a symlinked root would let an otherwise\n * valid name write/delete outside the isolated directory (e.g. onto authored\n * skills). Checked before composing any child path.\n */\nasync function assertManagedRootSafe(): Promise<void> {\n\tconst rootStat = await fs.lstat(getManagedSkillsDir()).catch(err => {\n\t\tif (isEnoent(err)) return null;\n\t\tthrow err;\n\t});\n\tif (rootStat?.isSymbolicLink()) {\n\t\tthrow new Error(\"The managed-skills root is a symlink; refusing to operate outside the managed directory.\");\n\t}\n}\n\nconst UPDATE_FILE_OPEN_FLAGS = fsConstants.O_WRONLY | fsConstants.O_NOFOLLOW;\n\nfunction assertManagedSkillFileSafeForUpdate(name: string, fileStat: Stats): void {\n\tif (!fileStat.isFile()) {\n\t\tthrow new Error(`Managed skill \"${name}\" SKILL.md is not a regular file; refusing to overwrite it.`);\n\t}\n\tif (fileStat.nlink > 1) {\n\t\tthrow new Error(\n\t\t\t`Managed skill \"${name}\" SKILL.md has ${fileStat.nlink} hard links; refusing to overwrite a file that may be user-authored elsewhere.`,\n\t\t);\n\t}\n}\n\nasync function openManagedSkillFileForUpdate(name: string, file: string) {\n\ttry {\n\t\treturn await fs.open(file, UPDATE_FILE_OPEN_FLAGS);\n\t} catch (err) {\n\t\tif ((err as { code?: string }).code === \"ELOOP\") {\n\t\t\tthrow new Error(`Managed skill \"${name}\" SKILL.md is a symlink; refusing to overwrite it.`);\n\t\t}\n\t\tthrow err;\n\t}\n}","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/autolearn/managed-skills.ts#L113-L149","documentation":"When overwriting an existing managed SKILL.md, the stat of the target must be a regular file. assertManagedSkillFileSafeForUpdate throws if it is a directory, FIFO, device, or other non-regular file, refusing to clobber something that isn't a plain file.","triggerScenarios":"writeManagedSkill (update path) stats an existing <name>/SKILL.md whose stat reports a non-regular file type — e.g. SKILL.md was replaced by a directory or a special file.","commonSituations":"Someone manually created a SKILL.md directory inside the managed skill folder; a broken tooling sync left a FIFO or socket at that path; a partial filesystem state after a crash.","solutions":["Inspect the path with `ls -la ~/.omp/agent/managed-skills/<name>/SKILL.md` to see what it actually is","Remove or rename the offending non-regular entry, then retry the write","If it should be a normal skill, recreate it: delete the bad entry and let writeManagedSkill create a fresh SKILL.md"],"exampleFix":"// before (shell): SKILL.md is a directory\nmv ~/.omp/agent/managed-skills/foo/SKILL.md ~/.omp/agent/managed-skills/foo/SKILL.md.bak-dir\n// after (shell): writeManagedSkill then recreates a regular file\nwriteManagedSkill({ name: \"foo\", action: \"update\", ... })","handlingStrategy":"validation","validationCode":"import { stat } from \"node:fs/promises\";\nconst st = await stat(skillMdPath).catch(() => null);\nif (st && !st.isFile()) throw new Error(\"SKILL.md is not a regular file\");","typeGuard":"function isRegularFile(st: { isFile(): boolean }): boolean {\n  return st.isFile();\n}","tryCatchPattern":"try {\n  await writeManagedSkill({ name, action: \"update\", ... });\n} catch (err) {\n  if (String((err as Error).message).includes(\"not a regular file\")) {\n    // inspect/remove the bad entry at managed-skills/<name>/SKILL.md, then retry\n  } else throw err;\n}","preventionTips":["Never replace a managed SKILL.md with a directory, FIFO, or device file","Inspect managed-skills contents after external tools touch ~/.omp","Let the managed-skills API create files instead of pre-seeding them manually"],"tags":["filesystem","validation","safety"],"backgroundTag":"not-a-regular-file","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}