{"record":{"id":"43ab09d3589ca41e","repo":"ReactiveX/rxjs","slug":"invalid-skill-installation-provenance","errorCode":null,"errorMessage":"Invalid Skill installation provenance.","messagePattern":"Invalid Skill installation provenance\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/migrate/src/skill-install.ts","lineNumber":285,"sourceCode":"    await rm(stageParent, { recursive: true, force: true });\n  }\n}\n\nfunction parseProvenance(source: string): SkillInstallProvenance {\n  const value = JSON.parse(source) as Partial<SkillInstallProvenance>;\n  if (\n    value.installSchemaVersion !== skillInstallSchemaVersion ||\n    value.schemaVersion !== skillIntegritySchemaVersion ||\n    value.packageName !== '@rxjs/migrate' ||\n    typeof value.packageVersion !== 'string' ||\n    value.digestAlgorithm !== 'sha256' ||\n    typeof value.digest !== 'string' ||\n    !Array.isArray(value.files) ||\n    (value.adapter !== 'agents' && value.adapter !== 'claude') ||\n    !Array.isArray(value.compatibleHarnesses) ||\n    typeof value.targetPath !== 'string'\n  ) {\n    throw new Error('Invalid Skill installation provenance.');\n  }\n  return value as SkillInstallProvenance;\n}\n\nasync function readProvenance(path: string): Promise<SkillInstallProvenance> {\n  return parseProvenance(await readFile(path, 'utf8'));\n}\n\nasync function tryReadProvenance(path: string): Promise<SkillInstallProvenance | undefined> {\n  try {\n    return await readProvenance(path);\n  } catch {\n    return undefined;\n  }\n}\n\nfunction sameContent(left: SkillIntegrity, right: SkillIntegrity): boolean {\n  return (","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/ReactiveX/rxjs/blob/54796b38a57e6309f9861e174737479bb3f63f61/packages/migrate/src/skill-install.ts#L267-L303","documentation":"Thrown by parseProvenance when the provenance JSON file (written next to an installed skill) does not match the expected schema: digest string, files array, adapter of 'agents'|'claude', compatibleHarnesses array, and targetPath string. It detects tampered, corrupted, or version-incompatible provenance metadata.","triggerScenarios":"readProvenance loading a .provenance file that was hand-edited, truncated, partially written, or produced by an older/newer incompatible @rxjs/migrate version (e.g. a new adapter id).","commonSituations":"Upgrading across versions that changed the schema; users editing hidden metadata files; disk corruption or interrupted writes.","solutions":["Delete the installed skill copy and its metadata, then reinstall with rxjs-migrate-skill install --force","Upgrade @rxjs/migrate so reader and writer schemas match","Avoid editing the provenance/metadata files under the installed skill directory"],"exampleFix":"# before: check fails on old provenance\nrxjs-migrate-skill check --harness claude\n# after\nrm -rf .claude/skills/rxjs-migrate\nrxjs-migrate-skill install --harness claude","handlingStrategy":"type-guard","validationCode":"const p = JSON.parse(raw);\nconst valid = typeof p.digest === 'string' && Array.isArray(p.files) && ['agents','claude'].includes(p.adapter) && Array.isArray(p.compatibleHarnesses) && typeof p.targetPath === 'string';","typeGuard":"const isSkillProvenance = (v: unknown): v is SkillInstallProvenance =>\n  !!v && typeof v === 'object' && typeof (v as any).digest === 'string' && Array.isArray((v as any).files) && ['agents','claude'].includes((v as any).adapter) && Array.isArray((v as any).compatibleHarnesses) && typeof (v as any).targetPath === 'string';","tryCatchPattern":"try { await readProvenance(path); } catch (e) { if (e instanceof Error && e.message === 'Invalid Skill installation provenance.') { /* wipe and reinstall skill */ } throw e; }","preventionTips":["Never edit provenance metadata files","Reinstall cleanly across version upgrades"],"tags":["cli","skill-install","schema-validation","corruption"],"backgroundTag":"schema-validation-failed","analyzedSha":"54796b38a57e6309f9861e174737479bb3f63f61","analyzedAt":"2026-08-28T10:21:27.410Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}