{"record":{"id":"72f85b3de634a5a2","repo":"paperclipai/paperclip","slug":"delivery-unknown","errorCode":"delivery_unknown","errorMessage":"Photon delivery is unknown; resolve this publication before retrying","messagePattern":"Photon delivery is unknown; resolve this publication before retrying","errorType":"error_code","errorClass":"PhotonError","httpStatus":null,"severity":"error","filePath":"server/src/services/photon/adapter.ts","lineNumber":494,"sourceCode":"    file: FileUpload | undefined,\n    options: { retryUnknown?: boolean; assertCurrent(): Promise<void> },\n  ): Promise<string> {\n    const key = `send:${publicationId}:${part}`;\n    const digest = createHash(\"sha256\")\n      .update(JSON.stringify(payload))\n      .digest(\"hex\");\n    let record = await this.state.update<SendRecord>(key, (current) => {\n      if (current && current.digest !== digest)\n        throw new Error(\"Photon publication payload changed after preparation\");\n      return current ?? { schema: 1, digest, phase: \"prepared\" };\n    });\n    if (record.phase === \"sent\" && record.messageGuid)\n      return record.messageGuid;\n    if (\n      (record.phase === \"sending\" || record.phase === \"uploading\") &&\n      !options.retryUnknown\n    )\n      throw new PhotonError(\n        \"delivery_unknown\",\n        \"Photon delivery is unknown; resolve this publication before retrying\",\n      );\n    const save = async (patch: Partial<SendRecord>) => {\n      record = await this.state.update<SendRecord>(key, (current) => {\n        if (!current || current.digest !== digest)\n          throw new Error(\"Photon send identity changed\");\n        return { ...current, ...patch };\n      });\n    };\n    if (file && !record.attachmentGuid) {\n      await options.assertCurrent();\n      await save({ phase: \"uploading\" });\n      try {\n        const uploaded = await this.client.attachments.upload({\n          fileName: file.filename,\n          data: file.data as Buffer,\n        });","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/photon/adapter.ts#L476-L512","documentation":"A PhotonError (code 'delivery_unknown') thrown in sendPart when the SendRecord for this publication part is in phase 'sending' or 'uploading' — meaning a previous attempt started but never recorded an outcome — and the caller did not pass retryUnknown: true. The adapter refuses to re-send a possibly-already-delivered message because iMessage has no read-back: a blind retry could deliver a duplicate.","triggerScenarios":"Retrying publish/sendPart for a part whose previous attempt crashed or lost connection after save({phase:'sending'}) or save({phase:'uploading'}) but before save({phase:'sent'}), without options.retryUnknown set.","commonSituations":"Process restart mid-send; network drop between sendText/sendAttachment call and receipt persistence; a timeout wrapped the send but the message actually went out; re-running an interrupted publication after a deploy.","solutions":["Resolve delivery out-of-band (check Photon/iMessage for the clientMessageId or messageGuid) before retrying","Re-call publish with options.retryUnknown: true if you accept the duplicate-delivery risk and Photon's clientMessageId dedup is relied upon","Only retry after confirming the original never appeared in the chat","Treat the publication as requiring human/operator resolution rather than automatic retry"],"exampleFix":"// before\nawait adapter.publish(id, pubId, msg, opts); // throws after crash mid-send\n// after\nawait adapter.publish(id, pubId, msg, { ...opts, retryUnknown: true }); // after verifying no duplicate was delivered","handlingStrategy":"retry","validationCode":"const record = await state.get(`send:${publicationId}:text-0`);\nif (record && (record.phase === 'sending' || record.phase === 'uploading')) {\n  // must resolve delivery out-of-band or pass retryUnknown\n}","typeGuard":"function isResolvable(record) {\n  return !record || ['prepared', 'uploaded'].includes(record.phase);\n}","tryCatchPattern":"try {\n  await adapter.publish(id, pubId, msg, opts);\n} catch (e) {\n  if (e instanceof PhotonError && e.code === 'delivery_unknown') {\n    const delivered = await checkPhotonForMessage(pubId); // out-of-band check\n    return adapter.publish(id, pubId, msg, { ...opts, retryUnknown: !delivered });\n  }\n  throw e;\n}","preventionTips":["Persist send state durably so phase transitions survive restarts","Always do an out-of-band delivery check before retryUnknown: true","Alert operators on publications stuck in sending/uploading phase","Rely on Photon's clientMessageId dedup for at-most-once semantics"],"tags":["idempotency","delivery-unknown","retry-safety"],"backgroundTag":"api-request-failed","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}