@@ -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