import type { IExecuteFunctions } from 'n8n-workflow'; import { NodeApiError } from 'n8n-workflow'; export function toCleanApiError( context: IExecuteFunctions, error: unknown, itemIndex: number, ): Error { const err = isRecord(error) ? error : {}; const statusCode = Number( err.statusCode ?? err.status ?? (isRecord(err.response) ? err.response.statusCode : undefined) ?? 0, ); const body = extractErrorBody(err); const detail = extractErrorMessage(body) || (typeof err.message === 'string' ? err.message : ''); const statusText = statusCode ? `HTTP ${statusCode}` : 'Request failed'; const message = detail ? `Obsidian API error (${statusText}): ${detail}` : `Obsidian API error (${statusText})`; return new NodeApiError( context.getNode(), { message, ...(statusCode ? { statusCode } : {}), ...(detail ? { detail } : {}) }, { message, description: detail || undefined, httpCode: statusCode ? String(statusCode) : undefined, itemIndex }, ); } function extractErrorBody(err: Record): unknown { if ('body' in err && err.body !== undefined) return err.body; const response = err.response; if (isRecord(response)) { if ('body' in response && response.body !== undefined) return response.body; if ('data' in response && response.data !== undefined) return response.data; } if ('error' in err && err.error !== undefined) return err.error; return undefined; } function extractErrorMessage(body: unknown): string { let data: unknown = body; if (typeof data === 'string') { const trimmed = data.trim(); if (!trimmed) return ''; try { data = JSON.parse(trimmed); } catch { return trimmed; } } if (isRecord(data)) { const candidate = data.detail ?? data.message ?? data.error; if (typeof candidate === 'string' && candidate) return candidate; if (isRecord(candidate) && typeof candidate.message === 'string') return candidate.message; } return ''; } function isRecord(value: unknown): value is Record { return typeof value === 'object' && value !== null; }