{"record":{"id":"fa724e1daf2ba0db","repo":"upstash/context7","slug":"failed-to-install-skill-name-errmsg","errorCode":null,"errorMessage":"Failed to install ${skill.name}: ${errMsg}","messagePattern":"Failed to install (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/cli/src/commands/skill.ts","lineNumber":457,"sourceCode":"          await symlinkSkill(skill.name, primarySkillDir, targetDir);\n        } catch (dirErr) {\n          const error = dirErr as NodeJS.ErrnoException;\n          if (error.code === \"EACCES\" || error.code === \"EPERM\") {\n            permissionError = true;\n            failedDirs.add(targetDir);\n          }\n          throw dirErr;\n        }\n      }\n\n      installedSkills.push(`${skill.project}/${skill.name}`);\n    } catch (err) {\n      const error = err as NodeJS.ErrnoException;\n      if (error.code === \"EACCES\" || error.code === \"EPERM\") {\n        continue;\n      }\n      const errMsg = err instanceof Error ? err.message : String(err);\n      log.warn(`Failed to install ${skill.name}: ${errMsg}`);\n    }\n  }\n\n  if (permissionError) {\n    installSpinner.fail(\"Permission denied\");\n    log.blank();\n    log.warn(\"Fix permissions with:\");\n    for (const dir of failedDirs) {\n      const parentDir = join(dir, \"..\");\n      log.dim(`  sudo chown -R $(whoami) \"${parentDir}\"`);\n    }\n    log.blank();\n    return;\n  }\n\n  installSpinner.succeed(`Installed ${installedSkills.length} skill(s)`);\n  trackEvent(\"install\", { skills: installedSkills, ides: targets.ides });\n","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/upstash/context7/blob/5284672feb575908efead6fcf1b5e542f8d607bb/packages/cli/src/commands/skill.ts#L439-L475","documentation":"Catch-all in the `context7 skill add` install loop. Permission errors (EACCES/EPERM) are diverted to a dedicated branch that prints chown instructions; any other error thrown while writing skill files or symlinking into agent skill directories (installSkillFiles / symlink steps) is reported here and the batch continues.","triggerScenarios":"ENOENT when the target skills directory or a path component does not exist; EEXIST when a file or symlink with the skill name already exists; ENOTDIR when a path component is a plain file; EMFILE/ENOSPC on descriptor or disk exhaustion; malformed file payload from a partial download.","commonSituations":"Dangling symlinks left by a partially removed previous install; agent skill folders moved/renamed after the CLI resolved targetDirs; full disks in CI containers; Windows path-length limits on deep skill paths.","solutions":["Delete stale artifacts: remove the existing skill directory or symlink under the agent's skills path shown in the error, then retry","Recreate the expected skills directory (e.g. mkdir -p ~/.claude/skills) if it was deleted, and re-run","Free disk space or file descriptors if the message shows ENOSPC/EMFILE","Reinstall from a fresh download: `context7 skill search <name> --install`"],"exampleFix":"# before — stale symlink causes EEXIST on install\nls -la ~/.claude/skills | grep my-skill\n\n# after — clean and reinstall\nrm -rf ~/.claude/skills/my-skill\ncontext7 skill add","handlingStrategy":"validation","validationCode":"import { access, constants, lstat, rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n// before install: writable target dir, no stale artifact\nawait access(targetDir, constants.W_OK);\nconst dest = join(targetDir, skillName);\nif (await lstat(dest).catch(() => null)) {\n  await rm(dest, { recursive: true, force: true });\n}","typeGuard":"function isFsError(e: unknown, code: string): e is NodeJS.ErrnoException {\n  return typeof e === \"object\" && e !== null && (e as NodeJS.ErrnoException).code === code;\n}","tryCatchPattern":"try {\n  await installSkillFiles(skill.name, downloadData.files, primaryDir);\n} catch (err) {\n  const code = (err as NodeJS.ErrnoException).code;\n  if (code === \"ENOENT\") await mkdir(primaryDir, { recursive: true });\n  if (code === \"EEXIST\") await rm(dest, { recursive: true, force: true });\n  throw err; // let the batch logger report anything else\n}","preventionTips":["Clean leftover skill directories/symlinks before reinstalling","Keep each agent's skills directory present and writable","Watch disk space on CI runners — ENOSPC surfaces here"],"tags":["filesystem","symlink","install","skills","enoent","eexist"],"backgroundTag":"file-write-failed","analyzedSha":"5284672feb575908efead6fcf1b5e542f8d607bb","analyzedAt":"2026-08-18T18:00:18.510Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}