{"record":{"id":"e695aba60a8250c0","repo":"remotion-dev/remotion","slug":"skill-is-not-installed","errorCode":null,"errorMessage":"${skill} is not installed.","messagePattern":"(.+?) is not installed\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/studio-server/src/preview-server/routes/install-remotion-skill.ts","lineNumber":50,"sourceCode":"\t\t\t'A skill is already being installed or removed. Please try again once it finishes.',\n\t\t);\n\t}\n\n\tchangingSkillsInProjects.add(remotionRoot);\n\ttry {\n\t\tconst installedSkill = getRemotionSkillsInfo({remotionRoot}).skills.find(\n\t\t\t({name}) => name === skill,\n\t\t);\n\t\tconst removingGlobally =\n\t\t\taction === 'remove' &&\n\t\t\tinstalledSkill?.installedInProject === false &&\n\t\t\tinstalledSkill.installedGlobally;\n\t\tif (\n\t\t\taction === 'remove' &&\n\t\t\t!removingGlobally &&\n\t\t\t!installedSkill?.installedInProject\n\t\t) {\n\t\t\tthrow new Error(`${skill} is not installed.`);\n\t\t}\n\n\t\tconst packageManager = getPackageManager({\n\t\t\tremotionRoot,\n\t\t\tpackageManager: undefined,\n\t\t\tdirUp: 0,\n\t\t\tlogLevel,\n\t\t});\n\t\tconst useBunx =\n\t\t\tpackageManager !== 'unknown' && packageManager.manager === 'bun';\n\t\tconst executable = useBunx\n\t\t\t? 'bunx'\n\t\t\t: process.platform === 'win32'\n\t\t\t\t? 'npx.cmd'\n\t\t\t\t: 'npx';\n\t\tconst commandArgs =\n\t\t\taction === 'install'\n\t\t\t\t? ['add', `remotion-dev/skills@${skill}`, '--yes']","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/remotion-dev/remotion/blob/46a3a6bf13ca367376ff18bbb06dae2e87e0d068/packages/studio-server/src/preview-server/routes/install-remotion-skill.ts#L32-L68","documentation":"When removing a skill locally (not globally), changeRemotionSkill first looks up the skill's installation status via getRemotionSkillsInfo. If the action is 'remove', removingGlobally is false, and the skill is not installed in the project, there is nothing to remove, so this error is thrown instead of running a pointless package-manager remove.","triggerScenarios":"Calling removeRemotionSkillHandler with action 'remove' for a skill whose installedInProject is false and which is not being removed globally — e.g. removing a skill that was never installed, or one that was installed globally only.","commonSituations":"A UI list is stale and shows a skill as installed when it is not; the skill was removed in another session already; the user confuses global vs project installation.","solutions":["Refresh the skills info (get-remotion-skills-info) and confirm the skill is actually installed in the project before removing","If the skill is installed globally, request a global removal instead of a project removal","Skip the removal if the skill is already absent — treat it as a no-op"],"exampleFix":"// before: blind remove\nawait removeSkill('@remotion/captions', {globally: false})\n// after: check first\nconst info = await getSkillsInfo();\nconst skill = info.skills.find((s) => s.name === '@remotion/captions');\nif (skill?.installedInProject) await removeSkill('@remotion/captions', {globally: false});","handlingStrategy":"validation","validationCode":"const info = await getRemotionSkillsInfo();\nconst skill = info.skills.find((s) => s.name === name);\nif (!skill?.installedInProject && !skill?.installedGlobally) {\n  // nothing to remove — skip\n}","typeGuard":"const canRemove = (s: typeof info.skills[number]) => s.installedInProject === true || s.installedGlobally === true;","tryCatchPattern":"try {\n  await removeSkill(skill);\n} catch (e) {\n  if (e.message.endsWith('is not installed.')) {\n    // treat as no-op\n  }\n}","preventionTips":["Refresh skills info before rendering remove buttons","Distinguish global vs project installs in the UI","Treat already-absent skills as successfully removed"],"tags":["validation","studio","skill-install"],"backgroundTag":"resource-not-found","analyzedSha":"46a3a6bf13ca367376ff18bbb06dae2e87e0d068","analyzedAt":"2026-09-18T00:12:20.256Z","contentChangedAt":"2026-09-18T00:12:20.256Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}