upstash/context7 · warning
Failed to write to ${skillPath}: ${error.message}
Error message
Failed to write to ${skillPath}: ${error.message} What it means
During skill-file installation in `generate`, write failures are classified: EACCES/EPERM routes to the permission-denied flow with `chown` hints, while every other errno (ENOSPC, EROFS, EISDIR, EMFILE...) is logged as a warning with the failing path and message, and that target is silently skipped — the command continues to the other targets.
Source
Thrown at packages/cli/src/commands/generate.ts:533
for (const targetDir of targetDirs) {
let finalDir = targetDir;
if (options.output && !targetDir.includes("/.config/") && !targetDir.startsWith(homedir())) {
finalDir = targetDir.replace(process.cwd(), options.output);
}
const skillDir = join(finalDir, skillName);
const skillPath = join(skillDir, "SKILL.md");
try {
await mkdir(skillDir, { recursive: true });
await writeFile(skillPath, generatedContent!, "utf-8");
} catch (err) {
const error = err as NodeJS.ErrnoException;
if (error.code === "EACCES" || error.code === "EPERM") {
permissionError = true;
failedDirs.add(skillDir);
} else {
log.warn(`Failed to write to ${skillPath}: ${error.message}`);
}
}
}
if (permissionError) {
writeSpinner.fail(pc.red("Permission denied"));
log.blank();
console.log(pc.yellow("Fix permissions with:"));
for (const dir of failedDirs) {
const parentDir = join(dir, "..");
console.log(pc.dim(` sudo chown -R $(whoami) "${parentDir}"`));
}
log.blank();
return;
}
writeSpinner.succeed(pc.green(`Created skill in ${targetDirs.length} location(s)`));
trackEvent("gen_install");View on GitHub (pinned to 5284672feb)
Solutions
- Check the errno in the logged message: ENOSPC → free disk space; EROFS → write to a writable location via `--output`
- Remove any directory conflicting with the SKILL.md file path
- Raise the file-descriptor limit (ulimit -n) for EMFILE
- Re-run generate after fixing and confirm the file exists at the printed path
Example fix
# before: read-only mount, warn + skipped context7 generate # Failed to write to .../SKILL.md: EROFS: read-only file system # after: direct output to a writable dir context7 generate --output ./out
Defensive patterns
Strategy: validation
Validate before calling
import { access } from 'fs/promises';
async function isWritable(dir: string): Promise<boolean> {
try { await access(dir === '' ? '.' : dir); return true; }
catch { return false; }
}
const ok = await isWritable(skillDir).catch(() => false);
if (!ok) throw new Error(`target not writable: ${skillDir}`); Type guard
function isPermissionErrno(e: unknown): e is NodeJS.ErrnoException {
return (e as NodeJS.ErrnoException)?.code === 'EACCES' || (e as NodeJS.ErrnoException)?.code === 'EPERM';
} Try / catch
try {
await mkdir(skillDir, { recursive: true });
await writeFile(skillPath, content, 'utf-8');
} catch (err) {
const code = (err as NodeJS.ErrnoException).code;
if (code === 'ENOSPC') throw new Error('disk full — free space or use --output');
if (code === 'EROFS') throw new Error('read-only filesystem — pass --output to a writable dir');
if (code === 'EISDIR') throw new Error(`remove the directory at ${skillPath} first`);
throw err;
} Prevention
- Pre-check target writability before generating, not after
- In containers/CI, write generated files to a writable workdir via --output
- Watch disk space in CI runners; ENOSPC mid-write is the most common non-permission cause
When it happens
Trigger: Disk full (ENOSPC); read-only filesystem such as a container volume or CI workspace (EROFS); an existing directory occupying the SKILL.md path (EISDIR); file-descriptor exhaustion (EMFILE).
Common situations: CI runners with full disks; Docker read-only mounts; a previous run or manual operation leaving a directory named SKILL.md; aggressive ulimits.
Related errors
- Expertise description is required
- Generation cancelled
- searchResult.message || "Try a different description"
- Please try again
- Fix permissions with:
AI-assisted analysis of upstash/context7@5284672feb (2026-08-18).
Data as JSON: /api/errors/acbe289b9d490f98.
Report an issue: GitHub.