Skip to content

Commit f5f4fa3

Browse files
committed
fix(webapp): check Plain mutation result.error, not just thrown errors
1 parent c598f5a commit f5f4fa3

1 file changed

Lines changed: 28 additions & 14 deletions

File tree

apps/webapp/app/utils/plain.server.ts

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ export async function sendToPlain({
3131
apiKey: env.PLAIN_API_KEY,
3232
});
3333

34-
// Best-effort support side-effect: the new client throws on failure, so we swallow and log
35-
// rather than break the user action that triggered it.
34+
// Best-effort support side-effect. Only transport/auth errors throw (caught below); business
35+
// and validation failures come back in each mutation's `result.error`, so we check those inline.
3636
try {
3737
const upsertCustomerRes = await client.mutation.upsertCustomer({
3838
input: {
@@ -58,11 +58,11 @@ export async function sendToPlain({
5858
},
5959
});
6060

61-
const customerId = upsertCustomerRes.customer?.id;
62-
if (!customerId) {
63-
console.error("Failed to upsert customer in Plain", upsertCustomerRes.result);
61+
if (upsertCustomerRes.error || !upsertCustomerRes.customer?.id) {
62+
console.error("Failed to upsert customer in Plain", upsertCustomerRes.error);
6463
return;
6564
}
65+
const customerId = upsertCustomerRes.customer.id;
6666

6767
// Attribute the thread to the org so support data can be rolled up per org: the tenant is
6868
// keyed by externalId = org_id. Isolated in its own try/catch, and the thread's
@@ -73,26 +73,37 @@ export async function sendToPlain({
7373
let tenantLinked = false;
7474
if (organizationId) {
7575
try {
76-
await client.mutation.upsertTenant({
76+
const tenantRes = await client.mutation.upsertTenant({
7777
input: {
7878
identifier: { externalId: organizationId },
7979
externalId: organizationId,
8080
name: organizationName ?? organizationId,
8181
},
8282
});
83-
await client.mutation.addCustomerToTenants({
84-
input: {
85-
customerIdentifier: { customerId },
86-
tenantIdentifiers: [{ externalId: organizationId }],
87-
},
88-
});
89-
tenantLinked = true;
83+
// Only link + attribute if the tenant genuinely upserted — a mutation error comes back in
84+
// `.error` (not thrown), and stamping the thread with a tenant that wasn't created would
85+
// make createThread itself fail.
86+
const membershipRes = tenantRes.error
87+
? undefined
88+
: await client.mutation.addCustomerToTenants({
89+
input: {
90+
customerIdentifier: { customerId },
91+
tenantIdentifiers: [{ externalId: organizationId }],
92+
},
93+
});
94+
if (tenantRes.error) {
95+
console.error("Failed to upsert Plain tenant", tenantRes.error);
96+
} else if (membershipRes?.error) {
97+
console.error("Failed to link Plain customer to tenant", membershipRes.error);
98+
} else {
99+
tenantLinked = true;
100+
}
90101
} catch (error) {
91102
console.error("Failed to link Plain customer to org tenant", error);
92103
}
93104
}
94105

95-
await client.mutation.createThread({
106+
const threadRes = await client.mutation.createThread({
96107
input: {
97108
customerIdentifier: {
98109
customerId,
@@ -103,6 +114,9 @@ export async function sendToPlain({
103114
tenantIdentifier: tenantLinked ? { externalId: organizationId } : undefined,
104115
},
105116
});
117+
if (threadRes.error) {
118+
console.error("Failed to create Plain thread", threadRes.error);
119+
}
106120
} catch (error) {
107121
console.error("Failed to send to Plain", error);
108122
}

0 commit comments

Comments
 (0)