FlowiseAI/Flowise · error · Error
Microsoft Graph request failed: ${error instanceof Error ? e
Error message
Microsoft Graph request failed: ${error instanceof Error ? error.message : 'Unknown error'} What it means
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.
Source
Thrown at packages/components/nodes/tools/MicrosoftTeams/core.ts:51
config.body = JSON.stringify(body)
}
try {
const response = await fetch(`${BASE_URL}${endpoint}`, config)
if (!response.ok) {
const errorText = await response.text()
throw new Error(`Microsoft Graph API error: ${response.status} ${response.statusText} - ${errorText}`)
}
// Handle empty responses for DELETE operations
if (method === 'DELETE' || response.status === 204) {
return { success: true, message: 'Operation completed successfully' }
}
return await response.json()
} catch (error) {
throw new Error(`Microsoft Graph request failed: ${error instanceof Error ? error.message : 'Unknown error'}`)
}
}
// Base Teams Tool class
abstract class BaseTeamsTool extends DynamicStructuredTool {
accessToken = ''
protected defaultParams: any
constructor(args: DynamicStructuredToolInput<any> & { accessToken?: string; defaultParams?: any }) {
super(args)
this.accessToken = args.accessToken ?? ''
this.defaultParams = args.defaultParams || {}
}
protected async makeTeamsRequest(endpoint: string, method: string = 'GET', body?: any) {
return await makeGraphRequest(endpoint, method as any, body, this.accessToken)
}
View on GitHub (pinned to abe4a8601a)
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.
Example fix
// before
catch (error) {
throw new Error(`Microsoft Graph request failed: ${error instanceof Error ? error.message : 'Unknown error'}`)
}
// after — preserve type, add cause, only wrap non-Error rejections
} catch (error) {
if (error instanceof Error) throw error
throw new Error('Microsoft Graph request failed: non-Error rejection', { cause: error })
} Defensive patterns
Strategy: try-catch
Validate before calling
// Verify egress + fetch availability before the first call
async function preflightNetwork() {
if (typeof fetch !== 'function') {
throw new Error('fetch is not defined — run Node >= 18 or polyfill undici')
}
const ctrl = new AbortController()
const t = setTimeout(() => ctrl.abort(), 5000)
try {
const r = await fetch('https://graph.microsoft.com/v1.0/$metadata', { signal: ctrl.signal })
if (!r.ok) console.warn('Graph reachable but returned', r.status)
} finally {
clearTimeout(t)
}
} Type guard
function isWrappedGraphFailure(e: unknown): e is Error {
return e instanceof Error && e.message.startsWith('Microsoft Graph request failed:')
}
function unwrapGraphError(e: unknown): string {
if (!isWrappedGraphFailure(e)) return String(e)
return e.message.replace(/^Microsoft Graph request failed:\s*/, '')
} Try / catch
try {
await tool.invoke(input)
} catch (e) {
const inner = unwrapGraphError(e)
if (inner.startsWith('Microsoft Graph API error:')) {
// reached Graph — handle per status (see error 440)
} else if (/fetch failed|ENOTFOUND|ECONNREFUSED|ECONNRESET/.test(inner)) {
// transport layer — check proxy/DNS/timeout
} else if (/Unexpected token|JSON/.test(inner)) {
// Graph returned non-JSON — likely a gateway error
}
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12).
Data as JSON: /api/errors/49dacb31c619a5ad.
Report an issue: GitHub.