davila7/claude-code-templates · warning

⚠ Error loading skill ${skillDir}:

Error message

  ⚠ Error loading skill ${skillDir}:

What it means

loadSkillsFromDirectory iterates skill directories and parses each SKILL.md; this inner warning fires when one specific skill directory fails (missing/unreadable SKILL.md despite passing an existence check, YAML frontmatter that throws, fs.stat failure). Only that skill is skipped — the loop continues and other skills still load.

Source

Thrown at cli-tool/src/skill-dashboard.js:93

            console.log(chalk.gray(`  ⊘ Skipping non-directory: ${skillDir}`));
            continue;
          }

          // Look for SKILL.md
          const skillMdPath = path.join(skillPath, 'SKILL.md');

          if (await fs.pathExists(skillMdPath)) {
            console.log(chalk.gray(`  ✓ Found SKILL.md in ${skillDir}`));
            const skillData = await this.parseSkill(skillMdPath, skillPath, skillDir, source);
            if (skillData) {
              skills.push(skillData);
              console.log(chalk.green(`  ✅ Loaded skill: ${skillData.name}`));
            }
          } else {
            console.log(chalk.gray(`  ⊘ No SKILL.md in ${skillDir}`));
          }
        } catch (error) {
          console.warn(chalk.yellow(`  ⚠ Error loading skill ${skillDir}:`), error.message);
        }
      }

      return skills;
    } catch (error) {
      console.warn(chalk.yellow(`Warning: Error loading skills from ${skillsDir}:`), error.message);
      return skills;
    }
  }

  async loadPluginSkills() {
    const skills = [];
    const pluginsDir = path.join(this.claudeDir, 'plugins', 'marketplaces');

    try {
      if (!(await fs.pathExists(pluginsDir))) {
        console.log(chalk.gray(`  ℹ Plugins directory does not exist: ${pluginsDir}`));
        return skills;

View on GitHub (pinned to a0851ed10c)

Solutions

  1. Identify the named skillDir from the warning and run `cat <skillDir>/SKILL.md` to confirm readability
  2. Validate the frontmatter YAML: extract the --- block and parse it with `yq` or a YAML linter
  3. Reinstall the skill or remove the broken directory so the scan is clean
  4. Fix permissions/symlinks (`ls -la`, `chmod -R u+r`) if the file exists but cannot be read

Example fix

# before
---
name:	my-skill   # tab, unquoted colon issues
---
# after
---
name: my-skill
---
Defensive patterns

Strategy: try-catch

Validate before calling

const fm = fs.readFileSync(skillMd, 'utf8').match(/^---\n[\s\S]*?\n---\n/);
if (!fm) { /* skip skill, no frontmatter to parse */ }

Try / catch

catch (error) {
  console.warn(`Skipping skill ${skillDir}: ${error.message}`);
  continue; // per-skill failure must not abort the directory scan
}

Prevention

When it happens

Trigger: Calling loadSkillsFromDirectory on a skills dir where one subdirectory contains a SKILL.md that is unreadable (permissions), is a broken symlink, has frontmatter yaml.load throws on (e.g. duplicate keys with certain yaml lib configs), or where fs.stat/readFile race with the file being deleted mid-scan.

Common situations: A skill was partially installed or uninstalled while the dashboard was loading; broken symlinks in a dotfile-managed skills directory; SKILL.md with invalid YAML frontmatter (tabs, unquoted special characters); skills dir synced from another OS with lost read permissions.

Related errors


AI-assisted analysis of davila7/claude-code-templates@a0851ed10c (2026-08-28). Data as JSON: /api/errors/278f98f37c0a397f. Report an issue: GitHub.