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

  1. Rebuild the archive dereferencing links: tar -czhf skill.tar.gz . (the -h flag follows symlinks) or use bsdtar --format zip
  2. Replace symlinks with real files or tiny stub files in the source repo
  3. Check for accidental symlinks: find . -type l
  4. 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

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


AI-assisted analysis of vercel-labs/skills@435076e789 (2026-08-28). Data as JSON: /api/errors/d9213f793f886ca5. Report an issue: GitHub.