Skip to content

Commit 3b7923e

Browse files
committed
fix(integrations): distinguish a transient Photon list failure from a stuck registration
The 409 re-key path read any missing match as "registered but Photon did not return it" and told the operator to delete the webhook by hand — including when the list call itself failed, where the right answer is simply to deploy again. A failed listing now throws its own retry-shaped error before the match is looked for, so manual cleanup is only ever advised for the state that actually requires it, and nothing is deleted off a read that never succeeded.
1 parent 4e11e89 commit 3b7923e

2 files changed

Lines changed: 28 additions & 2 deletions

File tree

apps/sim/lib/webhooks/providers/photon-imessage.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,25 @@ describe('photonImessageHandler', () => {
535535
).rejects.toThrow(/could not remove the stale registration/i)
536536
})
537537

538+
it('tells the operator to retry when listing webhooks fails, not to clean up by hand', async () => {
539+
const fetchMock = vi.fn(async (_url: RequestInfo | URL, init?: RequestInit) => {
540+
const method = init?.method ?? 'GET'
541+
if (method === 'POST') return new Response(JSON.stringify({}), { status: 409 })
542+
return new Response(JSON.stringify({}), { status: 503 })
543+
})
544+
vi.stubGlobal('fetch', fetchMock)
545+
546+
await expect(
547+
photonImessageHandler.createSubscription!(subscriptionContext(CREDS))
548+
).rejects.toThrow(/listing webhooks to re-key it failed with status 503/i)
549+
// A transient list failure must not read as the manual-cleanup case.
550+
await expect(
551+
photonImessageHandler.createSubscription!(subscriptionContext(CREDS))
552+
).rejects.not.toThrow(/dashboard/i)
553+
// Nothing was deleted on a read that never succeeded.
554+
expect(fetchMock.mock.calls.some((call) => call[1]?.method === 'DELETE')).toBe(false)
555+
})
556+
538557
it('fails clearly when Photon reports a conflict but does not list the webhook', async () => {
539558
const fetchMock = vi.fn(async (_url: RequestInfo | URL, init?: RequestInit) => {
540559
const method = init?.method ?? 'GET'

apps/sim/lib/webhooks/providers/photon-imessage.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,17 +324,24 @@ export const photonImessageHandler: WebhookProviderHandler = {
324324
//
325325
// Every step is checked. Re-registering over a stale record that is still there just earns
326326
// another 409, so a failure here has to surface as the thing the operator can act on rather
327-
// than as a second conflict with no explanation.
327+
// than as a second conflict with no explanation — and a transient fault has to read as
328+
// "try again", not as the manual cleanup that only an unrecoverable state calls for.
328329
logger.info(`[${requestId}] Photon webhook URL already registered; re-keying`)
329330

330331
const listed = await photonWebhooksRequest(projectId, projectSecret, '')
332+
if (listed.status >= 400) {
333+
throw new Error(
334+
`Photon reports ${webhookUrl} is already registered, but listing webhooks to re-key it failed with status ${listed.status}. Deploy again once Photon is reachable.`
335+
)
336+
}
337+
331338
const existing = (Array.isArray(listed.body.data) ? listed.body.data : []).find(
332339
(record: PhotonWebhookRecord) => record.webhookUrl === webhookUrl
333340
) as PhotonWebhookRecord | undefined
334341

335342
if (!existing?.id) {
336343
throw new Error(
337-
`Photon reports ${webhookUrl} is already registered but did not return it when listing webhooks (status ${listed.status}). Its signing secret can only be reissued by re-creating it — delete the webhook in the Photon dashboard, then deploy again.`
344+
`Photon reports ${webhookUrl} is already registered but did not return it when listing webhooks. Its signing secret can only be reissued by re-creating it — delete the webhook in the Photon dashboard, then deploy again.`
338345
)
339346
}
340347

0 commit comments

Comments
 (0)