jackwener/OpenCLI · warning · EmptyResultError

No installed skills.

Error message

No installed skills.

What it means

Thrown as an EmptyResultError when the skill config's managedSkills map (cfg.managedSkills) is missing or empty. The 'installed' command lists skills recorded in trae's skill configuration file; with no managed entries there are no rows.

Source

Thrown at clis/trae-solo/skill-fs.js:78

});

// -------- skill-fs-installed --------
cli({
    site: 'trae-solo',
    name: 'skill-fs-installed',
    access: 'read',
    description: 'List INSTALLED Trae SOLO skills (managedSkills entry in ~/.trae/skill-config.json).',
    domain: 'localhost',
    browser: false,
    strategy: Strategy.LOCAL,
    args: [],
    columns: ['Index', 'Name', 'Description', 'Source'],
    func: async () => {
        const cfg = readSkillConfig();
        const managed = cfg.managedSkills || {};
        const rows = Object.entries(managed);
        if (!rows.length) {
            throw new EmptyResultError('trae-solo skill-fs-installed', 'No installed skills.');
        }
        return rows.map(([name, source], i) => ({
            Index: i + 1,
            Name: name,
            Description: '',
            Source: source,
        }));
    },
});

// -------- skill-fs-show --------
cli({
    site: 'trae-solo',
    name: 'skill-fs-show',
    access: 'read',
    description: 'Print a skill\'s SKILL.md content + on-disk path.',
    domain: 'localhost',
    browser: false,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Install skills via the managed install command so they are registered in the skill config.
  2. Manually add entries to the config's managedSkills object, e.g. { "my-skill": "marketplace" }.
  3. Verify the skill config file path exists and was not reset; restore from backup if needed.
  4. If skills exist on disk but aren't listed, they were installed out-of-band — reinstall via the CLI to register them.

Example fix

// before (skill config)
{}
// after
{ "managedSkills": { "my-skill": "marketplace" } }
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
function hasManagedSkills(configPath) {
  if (!fs.existsSync(configPath)) return false;
  const cfg = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
  return cfg && typeof cfg.managedSkills === 'object' && Object.keys(cfg.managedSkills).length > 0;
}

Type guard

function hasManagedSkillsCfg(cfg) {
  return cfg != null && typeof cfg.managedSkills === 'object' && Object.keys(cfg.managedSkills || {}).length > 0;
}

Try / catch

try {
  const rows = await skillFsInstalled();
} catch (e) {
  if (e instanceof EmptyResultError && /No installed skills/.test(e.message)) {
    // fall back to scanning the skills dir or prompt install
  } else throw e;
}

Prevention

When it happens

Trigger: Running trae-solo skill-fs-installed when no skills were installed through the managed flow, the skill config file was deleted/reset, or readSkillConfig() returns a config without a managedSkills key.

Common situations: Fresh environment before any install; user installed skills manually by copying folders (bypassing the managed registry); config file corrupted or replaced by an older trae version with a different schema.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/ad95607ef66b470d. Report an issue: GitHub.