{"record":{"id":"54deceff21bcfe84","repo":"gitroomhq/postiz-app","slug":"bluesky-may-have-already-published-this-post-plea","errorCode":null,"errorMessage":"Bluesky may have already published this post, please check your account before posting again to avoid duplicates","messagePattern":"Bluesky may have already published this post, please check your account before posting again to avoid duplicates","errorType":"exception","errorClass":"BadBody","httpStatus":null,"severity":"warning","filePath":"libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts","lineNumber":481,"sourceCode":"          message: firstPost.message,\n          media: (firstPost.media || []).map((m) => ({\n            path: m.path,\n            alt: m.alt || '',\n          })),\n        } as BlueskyPendingData,\n      },\n    ];\n  }\n\n  override async checkPostStatus(\n    accessToken: string,\n    pendingData: BlueskyPendingData,\n    integration: Integration\n  ): Promise<PendingCheckResponse> {\n    // A confirmed create attempt died without reporting its result: never run\n    // the create again - stop with an explicit warning instead.\n    if (pendingData.attempting && pendingData.confirmed) {\n      throw new BadBody(\n        'bluesky',\n        JSON.stringify({}),\n        {} as any,\n        'Bluesky may have already published this post, please check your account before posting again to avoid duplicates'\n      );\n    }\n\n    // witness the armed create so finalizePost knows the attempt is uniquely\n    // accounted for before it mutates anything\n    const witness = (): PendingCheckResponse =>\n      pendingData.attempting && !pendingData.confirmed\n        ? {\n            status: 'ready',\n            pendingData: { ...pendingData, confirmed: true },\n          }\n        : { status: 'ready', pendingData };\n\n    // Image-only posts have no asynchronous processing step.","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts#L463-L499","documentation":"Thrown by Bluesky's checkPostStatus when pendingData shows a confirmed create attempt (attempting && confirmed) whose result was never reported. Because the post may already exist on Bluesky, the provider refuses to retry the create to avoid duplicates and stops with an explicit warning. This is a safety stop, not a transient failure.","triggerScenarios":"The post workflow crashed/timed out after marking pendingData.confirmed=true but before recording the created post URI (e.g. worker restart, activity timeout, network drop after the app.bsky.feed.post create call succeeded).","commonSituations":"Temporal worker restarts mid-publish, activity timeouts after the create RPC, network failure right after Bluesky accepted the post.","solutions":["Log into Bluesky (or query the app.bsky.feed.post search/resolver) and check whether the post exists","If it exists, mark the post as published in Postiz and delete the duplicate if unwanted","If it does not exist, reset pendingData (attempting/confirmed) and re-run the post","Investigate why the workflow died between confirm and result to prevent recurrence"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const res = await provider.checkPostStatus(entry, pendingData, integration);\n} catch (err) {\n  if (err instanceof BadBody && /already published/.test(err.message)) {\n    // surface to the user for manual confirmation, never auto-retry\n    await markNeedsUserReview(entry);\n    return;\n  }\n  throw err;\n}","preventionTips":["Alert on workflows that die after the confirm step","Monitor pendingData.attempting+confirmed state and quarantine those posts","Keep publish and result recording in the same activity where possible"],"tags":["bluesky","duplicate-protection","workflow-recovery"],"backgroundTag":"ambiguous-publish-outcome","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}