upstash/context7 · error

Fix permissions with:

Error message

Fix permissions with:

What it means

During the skill install loop, writes into target directories (agent skill folders such as ~/.claude/skills or project paths) threw Node filesystem errors with code EACCES or EPERM. The loop records permissionError and the failed directories, fails the spinner with 'Permission denied', and prints 'Fix permissions with:' followed by a `sudo chown -R $(whoami) <parentDir>` line per failing directory.

Source

Thrown at packages/cli/src/commands/skill.ts:464

          throw dirErr;
        }
      }

      installedSkills.push(`${skill.project}/${skill.name}`);
    } catch (err) {
      const error = err as NodeJS.ErrnoException;
      if (error.code === "EACCES" || error.code === "EPERM") {
        continue;
      }
      const errMsg = err instanceof Error ? err.message : String(err);
      log.warn(`Failed to install ${skill.name}: ${errMsg}`);
    }
  }

  if (permissionError) {
    installSpinner.fail("Permission denied");
    log.blank();
    log.warn("Fix permissions with:");
    for (const dir of failedDirs) {
      const parentDir = join(dir, "..");
      log.dim(`  sudo chown -R $(whoami) "${parentDir}"`);
    }
    log.blank();
    return;
  }

  installSpinner.succeed(`Installed ${installedSkills.length} skill(s)`);
  trackEvent("install", { skills: installedSkills, ides: targets.ides });

  const installedNames = selectedSkills.map((s) => s.name);
  logInstallSummary(targets, targetDirs, installedNames);
}

async function searchCommand(query: string): Promise<void> {
  trackEvent("command", { name: "search" });
  log.blank();

View on GitHub (pinned to 5284672feb)

Solutions

  1. Run exactly the suggested command for each listed directory: `sudo chown -R $(whoami) "<parentDir>"`, then retry the install.
  2. Alternatively pick a writable target: install to project scope instead of global, or vice versa, via the target flags.
  3. Never run `context7` itself with sudo — it creates root-owned config/skill dirs that cause exactly this error later.
  4. In containers/CI, ensure the runtime user owns the HOME and working directory.

Example fix

// before (common cause): running the CLI elevated creates root-owned dirs
sudo ctx7 skill add owner/repo
// after: fix ownership once, then always run unprivileged
sudo chown -R $(whoami) ~/.claude
ctx7 skill add owner/repo
Defensive patterns

Strategy: try-catch

Validate before calling

import { access, constants } from "node:fs/promises";

// Pre-check write access to every target dir before installing
for (const dir of targetDirs) {
  try {
    await access(dir, constants.W_OK);
  } catch {
    console.error(`No write permission for ${dir} - fix ownership first (sudo chown -R $(whoami) "${dir}/..").`);
    process.exit(1);
  }
}

Type guard

function isPermissionError(err: unknown): err is NodeJS.ErrnoException {
  return (
    err instanceof Error &&
    (err as NodeJS.ErrnoException).code === "EACCES" ||
    (err as NodeJS.ErrnoException).code === "EPERM"
  );
}

Try / catch

try {
  await writeFile(targetPath, content, "utf8");
} catch (err) {
  if (isPermissionError(err)) {
    permissionError = true;
    failedDirs.add(dir);
    continue; // collect all failing dirs, report once at the end
  }
  throw err;
}

Prevention

When it happens

Trigger: Target skill directory (or its parent) is owned by root or another user — typically because it was created earlier via sudo; read-only mount or macOS-protected path; container/CI environment where the CLI user lacks write access to the home or project dir.

Common situations: Previously ran the CLI (or the agent) with sudo, leaving root-owned ~/.claude or .agents directories; installing into a project directory on a read-only bind mount; locked-down corporate macOS home directories.

Related errors


AI-assisted analysis of upstash/context7@5284672feb (2026-08-18). Data as JSON: /api/errors/4b8409e64c09618d. Report an issue: GitHub.