{"record":{"id":"a2f8e0c144458063","repo":"slidevjs/slidev","slug":"slidev-the-length-of-stepranges-does-not-match-t","errorCode":null,"errorMessage":"[slidev] The length of stepRanges does not match the length of steps, this is an internal error.","messagePattern":"\\[slidev\\] The length of stepRanges does not match the length of steps, this is an internal error\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/client/builtin/ShikiMagicMove.vue","lineNumber":93,"sourceCode":"  if (!currentStep || !currentStep.code)\n    return\n\n  copy(currentStep.code.trim())\n}\n\n// Normalized the ranges, to at least have one range\nconst ranges = computed(() => props.stepRanges.map(i => i.length ? i : ['all']))\n\nonUnmounted(() => {\n  clicks?.unregister(id)\n})\n\nonMounted(() => {\n  if (!clicks)\n    return\n\n  if (ranges.value.length !== steps.length)\n    throw new Error('[slidev] The length of stepRanges does not match the length of steps, this is an internal error.')\n\n  const clickCounts = ranges.value.map(s => s.length).reduce((a, b) => a + b, 0)\n  const clickInfo = clicks.calculateSince(props.at, clickCounts - 1)\n  clicks.register(id, clickInfo)\n\n  let cancelTick: () => void = () => { }\n  watch(\n    () => clicks.current,\n    () => {\n      // Calculate the step and rangeStr based on the current click count\n      const clickCount = clickInfo ? clicks.current - clickInfo.start : CLICKS_MAX\n      let step = steps.length - 1\n      let currentClickSum = 0\n      let rangeStr = 'all'\n      for (let i = 0; i < ranges.value.length; i++) {\n        const current = ranges.value[i]\n        if (clickCount < currentClickSum + current.length - 1) {\n          step = i","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/slidevjs/slidev/blob/0d798ace5828966d9f77f62094d5f7a971ad98f7/packages/client/builtin/ShikiMagicMove.vue#L75-L111","documentation":"An internal invariant check in the `ShikiMagicMove` client component. `steps` is the decoded array of Shiki Magic-Move token steps (decompressed from the `stepsLz` base64 prop), and `ranges` is the normalized `stepRanges` prop. Both are emitted together by Slidev's markdown compiler for `{1|2|3}`-style animated code blocks, so their lengths must agree. A mismatch means the compiled payload is internally inconsistent and the click-mapping logic (which indexes `ranges.value[i]` against `steps`) would read out of bounds.","triggerScenarios":"Fires in `onMounted` when `ranges.value.length !== steps.length`. Because both props are generated by the same compiler pass for a single Magic-Move block, a mismatch implies corruption: a partially-overwritten/decompressed `stepsLz` whose decoded array length differs from `stepRanges`, a manual/programmatic instantiation of the component with mismatched props, or a version skew between the markdown compiler that emitted the props and the client component that validates them.","commonSituations":"Mixed @slidev/client and @slidev/parser versions where the Magic-Move fence compiler changed how it pairs `stepsLz` and `stepRanges`; a cached/stale transformed module in `node_modules/.vite` containing an old shape; hand-editing a compiled slide or rendering the component outside Slidev with inconsistent props.","solutions":["This is an internal error — file a Slidev bug with the offending Magic-Move code block and the @slidev package versions.","Ensure all @slidev/* packages share one version (dedupe node_modules); version skew between the compiler and client is the leading cause.","Clear Vite's transform cache (`node_modules/.vite`) and reload to discard a stale compiled module.","If rendering ShikiMagicMove manually, pass `stepsLz` and `stepRanges` produced by the same compile step so their lengths match."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// If you instantiate ShikiMagicMove.vue manually, assert the invariant first:\nimport lz from 'lz-string'\nfunction magicMovePropsConsistent(stepsLz: string, stepRanges: string[][]): boolean {\n  const steps = JSON.parse(lz.decompressFromBase64(stepsLz)) as unknown[]\n  const ranges = stepRanges.map(i => i.length ? i : ['all'])\n  return ranges.length === steps.length\n}","typeGuard":"function stepsAndRangesMatch(stepsLz: string, stepRanges: string[][]): boolean {\n  const steps = JSON.parse(lz.decompressFromBase64(stepsLz)) as unknown[]\n  return stepRanges.map(i => i.length ? i : ['all']).length === steps.length\n}","tryCatchPattern":null,"preventionTips":["Keep @slidev/client and @slidev/parser on the same version so the Magic-Move compiler and component agree on prop shape.","Clear `node_modules/.vite` after upgrading Slidev to drop stale compiled Magic-Move modules.","Never hand-edit the `stepsLz` / `stepRanges` props independently; they are a paired compiler output.","If you render ShikiMagicMove outside Slidev, generate both props from the same compile pass."],"tags":["slidev","vue-component","internal-error","shiki-magic-move","version-skew"],"backgroundTag":null,"analyzedSha":"0d798ace5828966d9f77f62094d5f7a971ad98f7","analyzedAt":"2026-08-12T17:10:56.221Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}