const STATUS_TITLES = { 400: 'Ungültige Anfrage', 401: 'Nicht angemeldet', 403: 'Zugriff verweigert', 404: 'Nicht gefunden', 409: 'Konflikt', 422: 'Ungültige Daten', 500: 'Serverfehler', 502: 'Gateway-Fehler', 503: 'Dienst nicht erreichbar', }; const GENERIC_HTTP_TITLES = new Set([ 'not found', 'unauthorized', 'forbidden', 'internal server error', 'bad request', 'service unavailable', ]); /** Normalize any thrown value into a stable backend error object. */ export function backendErrorFrom(err) { if (!err) { return { message: 'Unbekannter Fehler', status: null, path: null, method: null }; } if (typeof err === 'string') { return { message: err, status: null, path: null, method: null }; } if (err.message != null && (err.status != null || err.path != null || err.method != null)) { return { message: err.message, status: err.status ?? null, path: err.path ?? null, method: err.method ?? null, }; } if (err.message != null) { return { message: err.message, status: err.status ?? null, path: err.path ?? null, method: err.method ?? null, }; } return { message: String(err), status: null, path: null, method: null }; } /** Read structured error from a rejected RTK async thunk action. */ export function resolveBackendError(action) { if (action.payload) return backendErrorFrom(action.payload); return backendErrorFrom(action.error); } export function formatBackendError(error) { const normalized = backendErrorFrom(error); const { message, status, path, method } = normalized; const statusTitle = status != null ? STATUS_TITLES[status] : null; const genericTitle = message && GENERIC_HTTP_TITLES.has(message.trim().toLowerCase()) ? statusTitle : null; const title = statusTitle || genericTitle || (status != null ? `HTTP ${status}` : 'Backend-Fehler'); const detail = message && message.trim().toLowerCase() !== title?.trim().toLowerCase() && !GENERIC_HTTP_TITLES.has(message.trim().toLowerCase()) ? message : null; const request = path ? `${method || 'GET'} ${path}` : null; return { title, detail, status, request }; } export function catchBackendError(rejectWithValue) { return (err) => rejectWithValue(backendErrorFrom(err)); } export function isBackendFailure(error) { const normalized = backendErrorFrom(error); return normalized.status != null || normalized.path != null; }