{"record":{"id":"dbfe93089c403251","repo":"paperclipai/paperclip","slug":"import-transfer-is-missing-parts","errorCode":null,"errorMessage":"Import transfer is missing parts","messagePattern":"Import transfer is missing parts","errorType":"http","errorClass":null,"httpStatus":409,"severity":"error","filePath":"server/src/routes/companies.ts","lineNumber":917,"sourceCode":"        await removeImportTransferPart(importTransferSpoolRoot, run.id, partIndex);\n        res.status(410).json({ error: \"Import transfer expired — re-create it\" });\n        return;\n      }\n      res.json({ ok: true, index: partIndex, alreadyCompleted: false } satisfies CompanyImportTransferPartUploadResult);\n    },\n  );\n\n  // Resume polling: which parts are done, which are still missing.\n  router.get(`${COMPANY_IMPORT_TRANSFERS_ROUTE_PATH}/:transferId`, async (req, res) => {\n    assertBoard(req);\n    const run = await requireImportTransferRun(req);\n    const manifest = storedImportTransferManifest(run);\n    const missingParts = run.status === \"completed\" ? [] : await importTransferMissingParts(run, manifest);\n    res.json({\n      transferId: run.id,\n      status: run.status,\n      totalParts: manifest.parts.length,\n      completedParts: manifest.parts.length - missingParts.length,\n      missingParts,\n    } satisfies CompanyImportTransferStatus);\n  });\n\n  /**\n   * Resolve a completed transfer into the same raw preview/import body a\n   * single-shot zip upload produces: load the run, require every part, then\n   * assemble the spool and verify it against the declared whole-file hash.\n   * Shared by the transfer preview and apply routes; returns null after\n   * responding 409 when parts are still missing. A whole-file mismatch fails\n   * closed for both callers: every part verified individually but the whole\n   * does not match the declaration, so the spool is deleted and a resume\n   * re-uploads every part instead of re-assembling the same corrupt bytes.\n   *\n   * With `claimApply` (the apply route), the run is atomically claimed before\n   * the spool is touched: the import pipeline is not idempotent, so of any\n   * overlapping applies of this transfer exactly one may run it — a single\n   * guarded status flip to \"applying\" that losers see as 409. The claim is","sourceCodeStart":899,"sourceCodeEnd":935,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/routes/companies.ts#L899-L935","documentation":"Completeness guard in resolveImportTransferBody: the transfer run is active but the server's spool does not yet hold every declared part (some part uploads missing or swept), so assembling an import from it would be corrupt and the request is refused until all parts arrive.","triggerScenarios":"Thrown at server/src/routes/companies.ts:884 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Include the required field(s) in the request path, query, or body as named by the error message, then retry.","Check the API contract in packages/shared validators for the exact required shape of this endpoint."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}