{"record":{"id":"49dacb31c619a5ad","repo":"FlowiseAI/Flowise","slug":"microsoft-graph-request-failed-error-instanceof","errorCode":null,"errorMessage":"Microsoft Graph request failed: ${error instanceof Error ? error.message : 'Unknown error'}","messagePattern":"Microsoft Graph request failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/tools/MicrosoftTeams/core.ts","lineNumber":51,"sourceCode":"        config.body = JSON.stringify(body)\n    }\n\n    try {\n        const response = await fetch(`${BASE_URL}${endpoint}`, config)\n\n        if (!response.ok) {\n            const errorText = await response.text()\n            throw new Error(`Microsoft Graph API error: ${response.status} ${response.statusText} - ${errorText}`)\n        }\n\n        // Handle empty responses for DELETE operations\n        if (method === 'DELETE' || response.status === 204) {\n            return { success: true, message: 'Operation completed successfully' }\n        }\n\n        return await response.json()\n    } catch (error) {\n        throw new Error(`Microsoft Graph request failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n    }\n}\n\n// Base Teams Tool class\nabstract class BaseTeamsTool extends DynamicStructuredTool {\n    accessToken = ''\n    protected defaultParams: any\n\n    constructor(args: DynamicStructuredToolInput<any> & { accessToken?: string; defaultParams?: any }) {\n        super(args)\n        this.accessToken = args.accessToken ?? ''\n        this.defaultParams = args.defaultParams || {}\n    }\n\n    protected async makeTeamsRequest(endpoint: string, method: string = 'GET', body?: any) {\n        return await makeGraphRequest(endpoint, method as any, body, this.accessToken)\n    }\n","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/tools/MicrosoftTeams/core.ts#L33-L69","documentation":"Catch-all wrapper thrown by the outer try/catch in makeGraphRequest. It re-wraps every failure inside the try block — including the status check throw (440), the fetch() network rejection, and response.json() parse failures — into a single flat Error whose message is the inner error.message prefixed with 'Microsoft Graph request failed: '. The wrapping destroys the original Error type and stack, so callers cannot distinguish auth failure from DNS failure from JSON corruption without string-parsing the message.","triggerScenarios":"Any error raised inside the try block: error 440 (non-2xx response), fetch() rejecting due to DNS/TLS/timeout/offline, response.text() throwing on a locked body stream, or response.json() throwing when Graph returns non-JSON (e.g. an HTML 502 from a gateway).","commonSituations":"Corporate proxy or firewall blocking graph.microsoft.com; node fetch using a self-signed cert without NODE_EXTRA_CA_CERTS; offline/air-gapped dev box; Cloudflare/Azure front-door 5xx that returns HTML instead of JSON; misconfigured BASE_URL pointing at a sovereign cloud; running in an environment without global fetch (Node < 18) so fetch itself is undefined.","solutions":["Read the inner message — if it starts with 'Microsoft Graph API error:' the request reached Graph (see error 440); otherwise it is a transport/parse failure.","For transport failures: verify egress to https://graph.microsoft.com:443 works (curl -v), configure HTTP_PROXY/HTTPS_PROXY if behind a corporate proxy, and on Node < 18 polyfill fetch via undici or upgrade.","For JSON parse failures: log response.headers.get('content-type'); if it is text/html the request never reached Graph — check BASE_URL and DNS.","Refactor makeGraphRequest to rethrow the original Error (or a typed subclass) instead of constructing a new Error, preserving type and stack.","Add a request timeout via AbortController so a hung socket fails fast instead of relying on the platform default."],"exampleFix":"// before\ncatch (error) {\n    throw new Error(`Microsoft Graph request failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n}\n\n// after — preserve type, add cause, only wrap non-Error rejections\n} catch (error) {\n    if (error instanceof Error) throw error\n    throw new Error('Microsoft Graph request failed: non-Error rejection', { cause: error })\n}","handlingStrategy":"try-catch","validationCode":"// Verify egress + fetch availability before the first call\nasync function preflightNetwork() {\n  if (typeof fetch !== 'function') {\n    throw new Error('fetch is not defined — run Node >= 18 or polyfill undici')\n  }\n  const ctrl = new AbortController()\n  const t = setTimeout(() => ctrl.abort(), 5000)\n  try {\n    const r = await fetch('https://graph.microsoft.com/v1.0/$metadata', { signal: ctrl.signal })\n    if (!r.ok) console.warn('Graph reachable but returned', r.status)\n  } finally {\n    clearTimeout(t)\n  }\n}","typeGuard":"function isWrappedGraphFailure(e: unknown): e is Error {\n  return e instanceof Error && e.message.startsWith('Microsoft Graph request failed:')\n}\n\nfunction unwrapGraphError(e: unknown): string {\n  if (!isWrappedGraphFailure(e)) return String(e)\n  return e.message.replace(/^Microsoft Graph request failed:\\s*/, '')\n}","tryCatchPattern":"try {\n  await tool.invoke(input)\n} catch (e) {\n  const inner = unwrapGraphError(e)\n  if (inner.startsWith('Microsoft Graph API error:')) {\n    // reached Graph — handle per status (see error 440)\n  } else if (/fetch failed|ENOTFOUND|ECONNREFUSED|ECONNRESET/.test(inner)) {\n    // transport layer — check proxy/DNS/timeout\n  } else if (/Unexpected token|JSON/.test(inner)) {\n    // Graph returned non-JSON — likely a gateway error\n  }\n}","preventionTips":["Pin Node >= 18 so global fetch is always available.","Set HTTPS_PROXY and NODE_EXTRA_CA_CERTS in corporate environments.","Always pass an AbortController with a timeout — never rely on platform defaults.","Patch makeGraphRequest to rethrow the original Error instead of rewrapping, so type guards upstream still work.","Log response.headers.get('content-type') when status is non-2xx to distinguish HTML gateways from real Graph JSON errors."],"tags":["microsoft-graph","error-wrapping","network","typescript","debugging"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}