{"record":{"id":"8a4ba2ed97f20a64","repo":"davila7/claude-code-templates","slug":"warning-error-parsing-skill-skilldirname","errorCode":null,"errorMessage":"Warning: Error parsing skill ${skillDirName}","messagePattern":"Warning: Error parsing skill (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cli-tool/src/skill-dashboard.js","lineNumber":214,"sourceCode":"      const categorizedFiles = this.categorizeFiles(supportingFiles, markdownContent);\n\n      return {\n        name: frontmatter.name || skillDirName,\n        description: frontmatter.description || 'No description available',\n        allowedTools: frontmatter['allowed-tools'] || frontmatter.allowedTools || null,\n        source,\n        path: skillPath,\n        mainFile: 'SKILL.md',\n        mainFilePath: skillMdPath,\n        mainFileSize: this.formatFileSize(stats.size),\n        lastModified: stats.mtime,\n        fileCount: supportingFiles.length + 1, // +1 for SKILL.md\n        supportingFiles: categorizedFiles,\n        rawContent: content,\n        markdownContent\n      };\n    } catch (error) {\n      console.warn(chalk.yellow(`Warning: Error parsing skill ${skillDirName}`), error.message);\n      return null;\n    }\n  }\n\n  async scanSupportingFiles(skillPath) {\n    const files = [];\n    const self = this; // Preserve 'this' context\n\n    async function scanDirectory(dir, relativePath = '') {\n      const entries = await fs.readdir(dir);\n\n      for (const entry of entries) {\n        const fullPath = path.join(dir, entry);\n        const relPath = relativePath ? path.join(relativePath, entry) : entry;\n\n        try {\n          const stat = await fs.stat(fullPath);\n","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/davila7/claude-code-templates/blob/a0851ed10c7c60463dac8cfaaca124cf32d5804d/cli-tool/src/skill-dashboard.js#L196-L232","documentation":"parseSkill failed while reading or parsing a skill directory's SKILL.md, so it returns null and that skill is skipped from the skill dashboard. It is a non-fatal warning: the catch logs the error message and continues with the remaining skills.","triggerScenarios":"SKILL.md missing, unreadable (permissions), not valid UTF-8, or the file-read/frontmatter-extraction code inside the try block throws; also I/O races if the skill directory is deleted while scanning.","commonSituations":"Skill directory exists but SKILL.md was renamed or is empty; permissions issues; partially synced/edited skill folders; symlinks pointing to nonexistent targets.","solutions":["Verify the skill directory actually contains a readable SKILL.md","Check the logged error.message for the root cause (ENOENT vs EACCES vs parse)","Fix permissions (chmod) or restore/remove the broken skill directory","Re-run the dashboard and confirm the skill appears"],"exampleFix":"# before\nmy-skill/\n  notes.md\n# after (add SKILL.md with frontmatter)\nmy-skill/\n  SKILL.md\n  notes.md","handlingStrategy":"validation","validationCode":"const fs = require('fs/promises');\nasync function skillIsParseable(dir) {\n  const md = path.join(dir, 'SKILL.md');\n  try { await fs.access(md, fs.constants.R_OK); return true; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try { const s = await parseSkill(dir); if (!s) console.warn(`skipped ${dir}`); } catch (e) { /* parseSkill already catches; handle null */ }","preventionTips":["Always include a valid SKILL.md in every skill directory","Validate skill folders with a lint script before running the dashboard"],"tags":["filesystem","parsing","skills","cli"],"backgroundTag":"file-parse-failed","analyzedSha":"a0851ed10c7c60463dac8cfaaca124cf32d5804d","analyzedAt":"2026-08-28T14:11:56.058Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}