vercel-labs/skills · error
Archive missing root SKILL.md
Error message
Archive missing root SKILL.md
What it means
After extracting a registry artifact, the provider requires a root-level SKILL.md (files must contain the exact key 'SKILL.md'). If every extracted entry lives in a subdirectory (or the manifest is missing), 'Archive missing root SKILL.md' is thrown.
Source
Thrown at src/providers/wellknown.ts:750
if (!Number.isFinite(size) || size < 0) throw new Error('Invalid tar entry size');
offset += 512;
// Reject symlinks and hard links. Skip directories and metadata entries.
if (typeFlag === 0x32 || typeFlag === 0x31) {
throw new Error('Archive links are not supported');
}
const isFile = typeFlag === 0 || typeFlag === 0x30;
if (isFile) {
const content = tar.subarray(offset, offset + size);
this.addArchiveFile(files, path, new Uint8Array(content), runningTotal);
}
offset += Math.ceil(size / 512) * 512;
}
if (!files.has('SKILL.md')) throw new Error('Archive missing root SKILL.md');
return files;
}
private readTarString(buffer: Uint8Array, offset: number, length: number): string {
const slice = buffer.subarray(offset, offset + length);
const nul = slice.indexOf(0);
return new TextDecoder().decode(nul >= 0 ? slice.subarray(0, nul) : slice);
}
/**
* Convert a user-facing URL to a skill URL.
* For well-known, this extracts the base domain and constructs the proper path.
* Uses agent-skills as the primary path for new URLs.
*/
toRawUrl(url: string): string {
try {
const parsed = new URL(url);
if (url.toLowerCase().endsWith('/skill.md')) {View on GitHub (pinned to 435076e789)
Solutions
- Repackage from inside the skill directory so SKILL.md is at archive root: cd my-skill && tar -czf ../skill.tar.gz .
- Verify: tar -tzf skill.tar.gz should list './SKILL.md' or 'SKILL.md' first
- Fix filename casing to exactly 'SKILL.md'
- Re-publish the corrected artifact
Example fix
# before (archive root contains my-skill/SKILL.md) cd .. && tar -czf skill.tar.gz my-skill # after cd my-skill && tar -czf ../skill.tar.gz . # SKILL.md at root
Defensive patterns
Strategy: validation
Validate before calling
import { execSync } from 'node:child_process';
const root = execSync(`tar -tzf ${file}`).toString().split('\n')[0].replace(/^\./, '');
if (root !== '' && !root.endsWith('SKILL.md')) {
throw new Error('Archive wraps skill in a directory; SKILL.md must be at root');
} Type guard
function isMissingSkillMd(e: unknown): e is Error {
return e instanceof Error && /missing root SKILL\.md/i.test(e.message);
} Try / catch
try { await provider.fetchArtifact(url); }
catch (e) {
if (isMissingSkillMd(e)) return await provider.fetchArtifact(url.replace('/skill.tar.gz', '/skill-at-root.tar.gz'));
throw e;
} Prevention
- Package from inside the skill directory, not its parent
- Verify with tar -tzf that SKILL.md appears at the archive root
- Use the exact filename 'SKILL.md' (case-sensitive)
When it happens
Trigger: An archive where SKILL.md sits inside a folder (e.g. my-skill/SKILL.md) or is named differently (skill.md, Skill.md), or was excluded during packaging — extraction succeeds but the 'SKILL.md' key check fails.
Common situations: Packaging with a wrapper directory ('cd parent && tar -czf skill.tar.gz myskill/'); case-mismatched filenames from macOS/Windows; forgetting to include the manifest at all.
Related errors
- Downloaded URL is not a valid SKILL.md file or supported arc
- Unsupported archive format
- Unsafe archive path: ${path}
- Archive exceeds maximum unpacked size
- Archive contains too many files
AI-assisted analysis of vercel-labs/skills@435076e789 (2026-08-28).
Data as JSON: /api/errors/38994ee1aeb03745.
Report an issue: GitHub.