{"record":{"id":"bf2998e96551228f","repo":"hoppscotch/hoppscotch","slug":"typeof-result-left-string-result-left-re","errorCode":null,"errorMessage":"typeof result.left === \"string\" ? result.left : result.left.error.message","messagePattern":"typeof result\\.left === \"string\" \\? result\\.left : result\\.left\\.error\\.message","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/hoppscotch-common/src/services/gql-tab-connection.service.ts","lineNumber":1262,"sourceCode":"          ctx.error = {\n            type: result.left.error?.kind || \"error\",\n            message: (t: ReturnType<typeof getI18n>) => {\n              if (\n                result.left !== \"cancellation\" &&\n                typeof result.left === \"object\"\n              ) {\n                return (\n                  result.left.humanMessage?.description(t) ||\n                  t(\"graphql.operation_error\")\n                )\n              }\n              return \"Unknown\"\n            },\n            component: result.left.component,\n          }\n        }\n\n        throw new Error(\n          typeof result.left === \"string\"\n            ? result.left\n            : result.left.error.message\n        )\n      }\n\n      const relayResponse = result.right\n\n      const parsedResponse = await GQLResponse.toResponse(\n        relayResponse,\n        options\n      )\n\n      if (parsedResponse.type === \"error\") {\n        throw new Error(parsedResponse.error.message)\n      }\n\n      const timeEnd = Date.now()","sourceCodeStart":1244,"sourceCodeEnd":1280,"githubUrl":"https://github.com/hoppscotch/hoppscotch/blob/ac145e7f758151b41fd46d3e5f513886ce9068ba/packages/hoppscotch-common/src/services/gql-tab-connection.service.ts#L1244-L1280","documentation":"runTabGQLOperation executes the tab's GraphQL request via the relay/interceptor. When the transport resolves to an Either Left (network failure, non-2xx HTTP error, cancellation, or a structured kernel error), it sets the tab's error state and throws a plain Error whose message is either the left's string marker or left.error.message. This is the generic 'the GraphQL request itself failed at the transport level' error, distinct from GraphQL-level errors returned inside a 200 response.","triggerScenarios":"Calling runTabGQLOperation when the underlying relay request fails: DNS/connection errors, TLS problems, 401/403/500 responses to the query, CORS/interceptor failures, or cancellation (left === \"cancellation\").","commonSituations":"Backend down or URL wrong; expired auth token causing 401 on the query; server crashing with 500 on certain operations; browser interceptor blocked by CORS; user switching tabs cancelling an in-flight operation.","solutions":["Read the thrown message / result.left.error.message to identify transport vs HTTP cause.","Confirm the endpoint URL and that the server is reachable (curl the GraphQL endpoint with the same operation).","Refresh or fix credentials/headers — 401/403 here usually means auth config is wrong or expired.","For 5xx, check server logs for the failing operation; retry after the backend issue is fixed.","If the message is \"cancellation\", the run was superseded — rerun the operation if needed."],"exampleFix":"// before\nthrow new Error(typeof result.left === \"string\" ? result.left : result.left.error.message)\n// after\nif (result.left === \"cancellation\") return\nconst detail = typeof result.left === \"string\" ? result.left : result.left.error.message\nthrow Object.assign(new Error(`GraphQL request failed: ${detail}`), { cause: result.left })","handlingStrategy":"try-catch","validationCode":"// Ensure auth and URL are valid before running the operation\nconst probe = await fetch(url, { method: 'POST', headers: { 'content-type': 'application/json', ...authHeaders }, body: JSON.stringify({ query: '{ __typename }' }) })\nif (probe.status === 401 || probe.status === 403) throw new Error('Credentials rejected — refresh token/headers before running the operation')","typeGuard":"function isTransportLeft(left: unknown): left is string | { error: { message: string }; component?: unknown } {\n  return typeof left === 'string' || (typeof left === 'object' && left !== null && 'error' in left)\n}","tryCatchPattern":"try {\n  await runTabGQLOperation(tab, options)\n} catch (e) {\n  const msg = e instanceof Error ? e.message : String(e)\n  if (msg === 'cancellation') return\n  if (/401|403/i.test(msg)) promptReAuth()\n  else showToast('Request failed', msg)\n}","preventionTips":["Pre-flight auth with a cheap { __typename } query to catch expired tokens early","Filter \"cancellation\" results from retry/alert logic","Log result.left (the structured error) not just the message for diagnosability","Verify server health/5xx rates before blaming client configuration"],"tags":["network","graphql","http-error"],"backgroundTag":"graphql-request-failed","analyzedSha":"ac145e7f758151b41fd46d3e5f513886ce9068ba","analyzedAt":"2026-09-01T10:28:52.156Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}