{"record":{"id":"5508b303913a8435","repo":"siyuan-note/siyuan","slug":"skill-source-is-not-a-regular-file","errorCode":null,"errorMessage":"skill source is not a regular file","messagePattern":"skill source is not a regular file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/skill_manage.go","lineNumber":213,"sourceCode":"\t\treturn \"encoding\"\n\tcase errors.Is(err, ErrSkillTooLarge):\n\t\treturn \"tooLarge\"\n\t}\n\treturn \"\"\n}\n\nfunc readManagedSkillSource(root *os.Root, p string) (string, error) {\n\tfile, err := root.Open(p)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer file.Close()\n\tinfo, err := file.Stat()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif !info.Mode().IsRegular() {\n\t\treturn \"\", errors.New(\"skill source is not a regular file\")\n\t}\n\tif info.Size() > maxManagedSkillSourceSize {\n\t\treturn \"\", ErrSkillTooLarge\n\t}\n\tcontent, err := io.ReadAll(io.LimitReader(file, maxManagedSkillSourceSize+1))\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\t// UTF-8 BOM 随正文保留；二进制内容不会返回给文本编辑器。\n\tif err = validateManagedSkillSource(string(content)); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn string(content), nil\n}\n\n// 写入临时文件并同步后替换，发生写入错误时保留原文及其换行和元数据。\nfunc writeManagedSkillSource(root *os.Root, p, content string, create bool, revision string) error {\n\tif err := validateManagedSkillSource(content); err != nil {","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/util/skill_manage.go#L195-L231","documentation":"readManagedSkillSource opens a skill file and Stats it before reading; this error means the opened file descriptor does not refer to a regular file (e.g. a FIFO, device or special file). The library only returns UTF-8 text content to the editor, so non-regular sources are rejected before any read occurs.","triggerScenarios":"ManageSkillFiles read (or write/move/remove pre-checks) on a path that passed validateManagedSkillPath but whose root.Open(...).Stat() reports a non-regular mode — typically a FIFO, /dev-like node or similar placed at a skill file path; called during list to compute Editable, and before move/remove of SKILL.md.","commonSituations":"A special file was created at the skill path by another process or a misconfigured tooling script; a name that looks like a file is actually a named pipe set up for IPC inside the workspace.","solutions":["Replace the special file at the path with a regular text file containing the skill content","Identify which process created the special file and stop it from writing into data/storage/ai/agent/skills","Re-create the file via the skill management API (action \"write\") instead of manually"],"exampleFix":"// before (accidentally a FIFO)\nmkfifo data/storage/ai/agent/skills/my-skill/SKILL.md\n// after\nprintf -- '---\\nname: my-skill\\ndescription: x\\n---\\n' > data/storage/ai/agent/skills/my-skill/SKILL.md","handlingStrategy":"type-guard","validationCode":"info, err := os.Stat(filepath.Join(dataDir, \"storage/ai/agent/skills\", p))\nif err == nil && !info.Mode().IsRegular() {\n  // replace with a regular file before calling read\n}","typeGuard":"func isRegularFile(info os.FileInfo) bool { return info.Mode().IsRegular() }","tryCatchPattern":"if err := ManageSkillFiles(req); err != nil && strings.Contains(err.Error(), \"not a regular file\") {\n  // recreate the path as a regular text file\n}","preventionTips":["Create skill files only through the skill management API","Don't place FIFOs/devices/sockets inside workspace data","Check file types after restoring from unusual backups"],"tags":["filesystem","special-file","skills"],"backgroundTag":"file-read-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}