{"record":{"id":"59bf667c53f316d2","repo":"Stirling-Tools/Stirling-PDF","slug":"missing-file-entry-entry-filepath","errorCode":null,"errorMessage":"Missing file entry ${entry.filePath}","messagePattern":"Missing file entry (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/core/services/shareBundleUtils.ts","lineNumber":117,"sourceCode":"  rootOrder: string[];\n  sortedEntries: ShareBundleManifest[\"entries\"];\n  files: File[];\n} | null> {\n  const zip = await JSZip.loadAsync(blob);\n  const manifestEntry = zip.file(MANIFEST_FILENAME);\n  if (!manifestEntry) {\n    return null;\n  }\n\n  const manifestText = await manifestEntry.async(\"text\");\n  const manifest = JSON.parse(manifestText) as ShareBundleManifest;\n  const { rootOrder, sortedEntries } = resolveShareBundleOrder(manifest);\n\n  const files: File[] = [];\n  for (const entry of sortedEntries) {\n    const zipEntry = zip.file(entry.filePath);\n    if (!zipEntry) {\n      throw new Error(`Missing file entry ${entry.filePath}`);\n    }\n    const fileBlob = await zipEntry.async(\"blob\");\n    files.push(\n      new File([fileBlob], entry.name, {\n        type: entry.type,\n        lastModified: entry.lastModified,\n      }),\n    );\n  }\n\n  return { manifest, rootOrder, sortedEntries, files };\n}\n\nexport async function extractLatestFilesFromBundle(\n  blob: Blob,\n  filename: string,\n  contentType: string,\n): Promise<File[]> {","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/services/shareBundleUtils.ts#L99-L135","documentation":"Thrown by loadShareBundleEntries while unpacking a share bundle zip: the manifest (stirling-share.json) references entry.filePath, but no entry at that path exists in the zip.","triggerScenarios":"The bundle is truncated/corrupt; the manifest references a path that was never written; path case or separator mismatch; or producer/consumer schema versions differ.","commonSituations":"Incomplete download of the bundle; a ZIP tool that rewrote entry names (absolute paths, backslashes); manual edits to the bundle; version skew between the exporting and importing Stirling build.","solutions":["Re-download or re-share the bundle to rule out truncation.","Open the zip and confirm the listed filePaths actually exist.","Ensure producer and consumer share the same manifest.schemaVersion.","Handle the missing entry gracefully (skip it) instead of aborting the whole load."],"exampleFix":"// before\nconst zipEntry = zip.file(entry.filePath);\nif (!zipEntry) throw new Error(`Missing file entry ${entry.filePath}`);\n\n// after\nconst zipEntry = zip.file(entry.filePath) ?? zip.file(entry.filePath.replace(/\\\\\\//g, '/'));\nif (!zipEntry) {\n  console.warn(`Missing file entry ${entry.filePath}; skipping.`);\n  continue;\n}","handlingStrategy":"validation","validationCode":"const manifestPaths = new Set(sortedEntries.map((e) => e.filePath));\nconst present = new Set(Object.keys(zip.files));\nconst missing = [...manifestPaths].filter((p) => !present.has(p));\nif (missing.length) {\n  throw new Error(`Bundle missing entries: ${missing.join(', ')}`);\n}","typeGuard":"function bundleIsComplete(zip: JSZip, entries: ShareBundleManifest['entries']): boolean {\n  return entries.every((e) => zip.file(e.filePath) != null);\n}","tryCatchPattern":null,"preventionTips":["Before iterating, diff manifest filePaths against the zip's actual entries.","Normalize path separators when reading bundles produced on Windows.","Version-check manifest.schemaVersion to avoid producer/consumer mismatch."],"tags":["zip","share-bundle","manifest","data-integrity"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}