{"record":{"id":"0fed2ae7739b059a","repo":"mozilla/pdf.js","slug":"getpageindex-page-has-been-removed","errorCode":null,"errorMessage":"GetPageIndex: page has been removed.","messagePattern":"GetPageIndex: page has been removed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/display/api.js","lineNumber":3067,"sourceCode":"        );\n        this.#pageCache.set(pageIndex, page);\n        return page;\n      });\n    this.#pagePromises.set(pageIndex, promise);\n    return promise;\n  }\n\n  async getPageIndex(ref) {\n    if (!isRefProxy(ref)) {\n      throw new Error(\"Invalid pageIndex request.\");\n    }\n    const index = await this.messageHandler.sendWithPromise(\"GetPageIndex\", {\n      num: ref.num,\n      gen: ref.gen,\n    });\n    const pageNumber = this.pagesMapper.getPageNumber(index + 1);\n    if (pageNumber === 0) {\n      throw new Error(\"GetPageIndex: page has been removed.\");\n    }\n    return pageNumber - 1;\n  }\n\n  getAnnotations(pageIndex, intent) {\n    return this.messageHandler.sendWithPromise(\"GetAnnotations\", {\n      pageIndex: this.pagesMapper.getPageId(pageIndex + 1) - 1,\n      intent,\n    });\n  }\n\n  getFieldObjects() {\n    return this.#cacheSimpleMethod(\"GetFieldObjects\");\n  }\n\n  getSignatures() {\n    return this.#cacheSimpleMethod(\"GetSignatures\");\n  }","sourceCodeStart":3049,"sourceCodeEnd":3085,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/display/api.js#L3049-L3085","documentation":"Thrown by PDFDocumentProxy.getPageIndex(ref) after the worker resolves the cross-reference index but pagesMapper.getPageNumber maps that index to 0. A 0 result means the page exists in the PDF structure tree but is not part of the currently active page set — i.e., it was deleted or excluded by an incremental update or by a page tree reorganization.","triggerScenarios":"Resolving a ref that points to a page node removed via a later PDF revision; using a ref cached from an older copy of the document after it was reloaded; documents whose /Pages /Count or /Kids exclude nodes the ref points to.","commonSituations":"Incrementally updated PDFs that delete pages but leave dangling references in outlines/named destinations; annotated PDFs re-saved by tools that rewrite the page tree; opening a PDF whose /Pages tree is inconsistent with its /Count.","solutions":["Treat this as a soft error: catch and skip the destination, falling back to the next valid page.","Validate the destination is still reachable via pdfDocument.getPage(pageNumber) before resolving child refs.","Regenerate or repair the PDF (e.g., re-save via a PDF optimizer) to prune stale refs."],"exampleFix":"// before\nconst idx = await pdfDocument.getPageIndex(ref);\n\n// after\ntry {\n  const idx = await pdfDocument.getPageIndex(ref);\n  await pdfDocument.getPage(idx + 1);\n} catch (e) {\n  if (e.message === 'GetPageIndex: page has been removed.') {\n    // destination is stale; skip or default to page 1\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":"const idx = await pdf.getPageIndex(ref).catch(e => {\n  if (e.message === 'GetPageIndex: page has been removed.') return -1;\n  throw e;\n});\nif (idx < 0) { /* stale destination */ }","typeGuard":"null","tryCatchPattern":"try {\n  return await pdf.getPageIndex(ref);\n} catch (e) {\n  if (e.message === 'GetPageIndex: page has been removed.') return null;\n  throw e;\n}","preventionTips":["Treat outline/named destinations as untrusted — they may point at removed pages.","After resolving a ref once, cache the result so stale refs are not re-resolved repeatedly.","Validate the destination page with getPage before navigating."],"tags":["pdf-structure","destinations","stale-ref"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}