vercel-labs/skills · error
Archive links are not supported
Error message
Archive links are not supported
What it means
extractTarGz rejects tar entries whose type flag is a symlink (0x32, '2') or hard link (0x31, '1'). Link entries could point outside the archive, so extraction refuses them outright.
Source
Thrown at src/providers/wellknown.ts:738
let offset = 0;
while (offset + 512 <= tar.length) {
const header = tar.subarray(offset, offset + 512);
if (header.every((byte) => byte === 0)) break;
const name = this.readTarString(header, 0, 100);
const sizeText = this.readTarString(header, 124, 12).trim();
const typeFlag = header[156];
const prefix = this.readTarString(header, 345, 155);
const path = prefix ? `${prefix}/${name}` : name;
const size = Number.parseInt(sizeText || '0', 8);
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);View on GitHub (pinned to 435076e789)
Solutions
- Rebuild the archive dereferencing links: tar -czhf skill.tar.gz . (the -h flag follows symlinks) or use bsdtar --format zip
- Replace symlinks with real files or tiny stub files in the source repo
- Check for accidental symlinks: find . -type l
- Re-publish the fixed artifact to the registry
Example fix
# before tar -czf skill.tar.gz . # after tar -czhf skill.tar.gz . # -h dereferences symlinks into real files
Defensive patterns
Strategy: validation
Validate before calling
import { execSync } from 'node:child_process';
const links = execSync(`tar -tvf ${file} | grep -E '^[hl]' || true`).toString().trim();
if (links) throw new Error(`Archive contains link entries:\n${links}`); Type guard
function isArchiveLinkError(e: unknown): e is Error {
return e instanceof Error && /links are not supported/i.test(e.message);
} Try / catch
try { await provider.fetchArtifact(url); }
catch (e) {
if (isArchiveLinkError(e)) {
notifyPublisher('Repack with tar -czhf (dereference symlinks)');
return null;
}
throw e;
} Prevention
- Package with tar -h or bsdtar to dereference symlinks
- Audit repos for committed symlinks: find . -type l
- Never repackage archives preserving link entries for this provider
When it happens
Trigger: A registry artifact containing symlink/hardlink entries — common when archiving a directory that itself contains symlinks (e.g. node_modules/.bin, or a SKILL.md symlinked to docs) without dereferencing.
Common situations: macOS/Linux skill repos with symlinks committed; packaging with tar default settings that preserve links instead of dereferencing them.
Related errors
- Unsafe archive path: ${path}
- Archive exceeds maximum unpacked size
- Archive contains too many files
- Invalid tar entry size
- Archive contains unsafe path: ${path}
AI-assisted analysis of vercel-labs/skills@435076e789 (2026-08-28).
Data as JSON: /api/errors/d9213f793f886ca5.
Report an issue: GitHub.