{"record":{"id":"4921e2984270e04e","repo":"mozilla/pdf.js","slug":"extractpages-partial-pageindices-cannot-be-combin","errorCode":null,"errorMessage":"extractPages: partial pageIndices cannot be combined with insertAfter entries.","messagePattern":"extractPages: partial pageIndices cannot be combined with insertAfter entries\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/core/editor/pdf_editor.js","lineNumber":879,"sourceCode":"        insertAfterList.push({ i, insertAfter: info.insertAfter, count });\n      }\n    }\n    if (insertAfterList.length === 0) {\n      return pageInfos;\n    }\n\n    const hasContent = info => !!(info.document || info.image);\n\n    // Partial pageIndices rely on auto-fill in extractPages, which races with\n    // the slots insertAfter assigns here.\n    for (let i = 0; i < pageInfos.length; i++) {\n      const info = pageInfos[i];\n      if (\n        hasContent(info) &&\n        info.pageIndices &&\n        info.pageIndices.length < counts[i]\n      ) {\n        throw new Error(\n          \"extractPages: partial pageIndices cannot be combined with insertAfter entries.\"\n        );\n      }\n    }\n\n    insertAfterList.sort((a, b) => a.insertAfter - b.insertAfter || a.i - b.i);\n\n    // If there is no base sequential sequence, resolve insertAfter against the\n    // explicit layout. Shift pageIndices values but keep their array order:\n    // extractPages maps each filtered source page to the corresponding\n    // pageIndices entry.\n    if (\n      sequence.length === 0 &&\n      pageInfos.some(info => hasContent(info) && info.pageIndices)\n    ) {\n      const updatedPageInfos = pageInfos.slice();\n      let maxExistingPos = -1;\n      for (const info of pageInfos) {","sourceCodeStart":861,"sourceCodeEnd":897,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/editor/pdf_editor.js#L861-L897","documentation":"Plain Error thrown by #resolveInsertAfterIndices during extractPages when at least one pageInfo uses insertAfter and another uses a partial pageIndices (fewer entries than the document's filtered page count). insertAfter relies on auto-filling sequential slots, which races with the explicit slot assignment partial pageIndices performs; the two cannot be combined deterministically.","triggerScenarios":"Calling the editor/extractPages API (used by PDFDocumentProxy.copyPages / insertPage-style operations) with a pageInfos array where one entry has insertAfter set and another has pageIndices shorter than its filtered page count.","commonSituations":"Custom integrations building new documents from multiple sources where some inserts use insertAfter and others use partial pageIndices.","solutions":["Pick one placement strategy: convert all entries to explicit pageIndices, or use insertAfter for all.","If you need both, pre-resolve insertAfter into explicit pageIndices yourself before calling extractPages.","Validate the pageInfos shape before invoking the editor API."],"exampleFix":"// before\npageInfos = [\n  { document, pageIndices: [0] },           // partial\n  { document, insertAfter: 2 },              // incompatible\n];\n\n// after — use explicit pageIndices everywhere\npageInfos = [\n  { document, pageIndices: [0] },\n  { document, pageIndices: [3] },            // pre-computed target slot\n];","handlingStrategy":"validation","validationCode":"function normalizePageInfos(pageInfos) {\n  const usesInsertAfter = pageInfos.some(p => p.insertAfter !== undefined);\n  const partial = pageInfos.some(p => p.pageIndices && p.pageIndices.length < (p.document?.numPages ?? 1));\n  if (usesInsertAfter && partial) {\n    throw new Error('Cannot mix insertAfter with partial pageIndices; resolve all to explicit pageIndices.');\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await editor.extractPages(pageInfos, ...);\n} catch (e) {\n  if (e.message.includes('partial pageIndices cannot be combined')) {\n    pageInfos = resolveAllToExplicitIndices(pageInfos);\n    return editor.extractPages(pageInfos, ...);\n  }\n  throw e;\n}","preventionTips":["Pick one placement strategy per extractPages call.","Resolve insertAfter into explicit pageIndices upstream if you need both behaviors.","Add a unit test that asserts your pageInfos builder never mixes the two."],"tags":["editor","extract-pages","validation","page-layout"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}