Troubleshooting skills catalog indexing: from scan to syscall mismatch
Back to blog

Troubleshooting skills catalog indexing: from scan to syscall mismatch

9/21/2026 · 3 min · DevOps

Troubleshooting skills catalog indexing: from scan to syscall mismatch#

Recently, I needed to set up a skills catalog extension (skills-vscode) on my Linux server environment. The tool has a straightforward design: it accepts a list of catalog sources (remote Git via SSH/HTTPS, organization repositories, or local filesystem paths), scans these sources for SKILL.md definition files, and generates a structured local index for IDE consumption.

While the automation flow seems simple, abstraction layers between applications and the underlying filesystem frequently produce unexpected behavior. Here is the technical breakdown of the issue, log analysis, operating system diagnostic, and the practical fix to get indexing running reliably.


The discovery lifecycle#

Under the hood, a catalog indexer operates through a lifecycle split between network operations and local system calls:

  1. Remote Sources (Git via HTTPS/SSH):

The extension executes shallow clones (git clone --depth 1) or targeted fetches into a temporary directory (such as /tmp/skills-vscode-*), avoiding full commit history transfers and saving disk I/O.

  1. Local Sources (Local Path):

The engine reads absolute or relative paths directly from the filesystem using native system calls (stat(), openat(), getdents64()).

  1. Scanning and Filtering:

The scanner traverses the directory tree looking strictly for the expected signature: SKILL.md.

  1. Metadata Persistence:

Upon finding valid definition files, the parser extracts the markdown content and persists the consolidated index into global storage (catalog-index.json).


The issue: indexing completed with 0 skills#

After configuring a public test repository source, I triggered the scan routine. The process finished without runtime errors, but the resulting index was empty.

Inspecting the detailed dashboard log revealed the following sequence:

[dashboard] search merged results=10 (returned=10)
[debug][discoverSkillsWithSubpathFallback] repoDir=/tmp/skills-vscode-kdDUha candidates=[null]
[debug][discoverSkills] basePath=/tmp/skills-vscode-kdDUha subpath=(none) searchPath=/tmp/skills-vscode-kdDUha
[debug][discoverSkills] priority dir hit: /tmp/skills-vscode-kdDUha (9 entries)
[debug][discoverSkills] after priority scan: 0 skills found
[debug][discoverSkills] falling back to findSkillDirs on: /tmp/skills-vscode-kdDUha
[debug][discoverSkills] findSkillDirs found dirs: []
[debug][discoverSkills] final result: (none)
[debug][discoverSkillsWithSubpathFallback] subpath=undefined => 0 skills
[debug][discoverSkillsWithSubpathFallback] all candidates exhausted, 0 skills
[info] catalog index saved: /root/.antigravity-server/data/User/globalStorage/gaoyuan.skills-vscode/catalog-index.json (0 skills)

Checking the global storage JSON confirmed the mismatch:

cd /root/.antigravity-server/data/User/globalStorage/gaoyuan.skills-vscode/
cat catalog-index.json
{
  "updatedAt": "2026-03-28T21:52:00.511Z",
  "sourcesHash": "b73bc4d67518db8629a8571df06fea1d3e7c5485",
  "sources": [
    {
      "source": "https://github.com/example-org/catalog-templates.git",
      "skillCount": 0,
      "lastIndexedAt": "2026-03-28T21:52:00.510Z",
      "availableRefs": [
        "fix/example-branch",
        "main",
        "topic/feature"
      ],
      "currentRef": "main"
    }
  ],
  "entries": []
}

Root cause analysis#

Evaluating the log trace isolated the failure point:

  1. Network and Git operations succeeded: The extension authenticated, queried the remote repository, mapped remote branches (availableRefs), and checked out the main branch into /tmp/skills-vscode-kdDUha.
  2. Disk I/O responded normally: The log noted priority dir hit: /tmp/skills-vscode-kdDUha (9 entries). Those 9 entries were root files and folders (README.md, .git, license, template directories, etc.).
  3. File contract was violated (Schema/Signature Mismatch): The target repository organized its definitions under generic template files (such as catalog-info.yaml or template.yaml). The extension scanner, however, strictly filters for SKILL.md.

Furthermore, on Linux filesystems (ext4 or xfs), path resolution is case-sensitive. If a repository contains skill.md, Skill.md, or SKILL.yaml, Node.js and libuv syscalls will not match unless explicit case fallbacks exist. Without the exact filename, findSkillDirs returns empty ([]) and writes entries: [].


Validation and practical fix#

To verify the scanner behavior and confirm the problem was purely contract-based, I created a local catalog test on the server.

1. Creating the expected structure#

Create a local directory structure with the required SKILL.md file:

mkdir -p /root/my-catalog/linux-sre

Generate the skill definition:

cat <<EOF > /root/my-catalog/linux-sre/SKILL.md
# Linux SRE L3 Tuning
Description: Advanced kernel tuning and system optimization definitions.
---
## Skills
- sysctl-optimization
- io-scheduler-tuning
- oom-killer-config
EOF

2. Updating catalogSources#

Configure the extension to read the local path directly:

{
  "skills.catalogSources": [
    "/root/my-catalog"
  ]
}

You can also combine multiple source types based on your workflow:

{
  "skills.catalogSources": [
    "https://github.com/my-org/skills-repo.git",
    "[email protected]:my-org/private-skills.git",
    "/root/my-catalog"
  ]
}

CLI diagnostic cheat sheet#

When debugging silent indexing failures, these commands help validate the environment before triggering the extension:

find /tmp/skills-vscode-* -name "SKILL.md"
strace -f -e trace=openat,access -p <PID> 2>&1 | grep -i SKILL
ssh -vT [email protected]

Practical indexing takeaways#

When catalog indexing tools fail silently or return empty lists, the key is separating transport/permission failures from contract/schema mismatches.

In this scenario, transport and cloning were functioning properly; the root cause was the strict expectation of SKILL.md filenames against repositories using alternative schemas. Conforming to the expected naming convention immediately allows the scanner to traverse directory trees and populate the index as intended.

Was this article helpful?

Leave a quick reaction to help prioritize future technical guides:

CC BY-NC

This post is licensed under CC BY-NC.

Comments

Join the discussion below.

0 comments