fix: enhance error messages when Fetch API fails (#893)

This commit is contained in:
Gauthier
2024-07-27 01:43:16 +02:00
committed by GitHub
parent 3fc14c9e22
commit fccfca6ed0
16 changed files with 308 additions and 59 deletions

View File

@@ -68,7 +68,10 @@ class ExternalAPI {
if (!response.ok) { if (!response.ok) {
const text = await response.text(); const text = await response.text();
throw new Error( throw new Error(
`${response.status} ${response.statusText}${text ? ': ' + text : ''}` `${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
{
cause: response,
}
); );
} }
const data = await this.getDataFromResponse(response); const data = await this.getDataFromResponse(response);
@@ -106,6 +109,15 @@ class ExternalAPI {
}, },
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
{
cause: response,
}
);
}
const resData = await this.getDataFromResponse(response); const resData = await this.getDataFromResponse(response);
if (this.cache) { if (this.cache) {
@@ -141,6 +153,15 @@ class ExternalAPI {
}, },
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
{
cause: response,
}
);
}
const resData = await this.getDataFromResponse(response); const resData = await this.getDataFromResponse(response);
if (this.cache) { if (this.cache) {
@@ -163,6 +184,15 @@ class ExternalAPI {
...config?.headers, ...config?.headers,
}, },
}); });
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
{
cause: response,
}
);
}
const data = await this.getDataFromResponse(response); const data = await this.getDataFromResponse(response);
return data; return data;
@@ -197,6 +227,17 @@ class ExternalAPI {
...config?.headers, ...config?.headers,
}, },
}).then(async (response) => { }).then(async (response) => {
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${
text ? ': ' + text : ''
}`,
{
cause: response,
}
);
}
const data = await this.getDataFromResponse(response); const data = await this.getDataFromResponse(response);
this.cache?.set(cacheKey, data, ttl ?? DEFAULT_TTL); this.cache?.set(cacheKey, data, ttl ?? DEFAULT_TTL);
}); });
@@ -212,6 +253,15 @@ class ExternalAPI {
...config?.headers, ...config?.headers,
}, },
}); });
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
{
cause: response,
}
);
}
const data = await this.getDataFromResponse(response); const data = await this.getDataFromResponse(response);
if (this.cache) { if (this.cache) {
@@ -250,13 +300,13 @@ class ExternalAPI {
} }
private async getDataFromResponse(response: Response) { private async getDataFromResponse(response: Response) {
const contentType = response.headers.get('Content-Type')?.split(';')[0]; const contentType = response.headers.get('Content-Type');
if (contentType === 'application/json') { if (contentType?.includes('application/json')) {
return await response.json(); return await response.json();
} else if ( } else if (
contentType === 'application/xml' || contentType?.includes('application/xml') ||
contentType === 'text/html' || contentType?.includes('text/html') ||
contentType === 'text/plain' contentType?.includes('text/plain')
) { ) {
return await response.text(); return await response.text();
} else { } else {

View File

@@ -152,7 +152,7 @@ class JellyfinAPI extends ExternalAPI {
try { try {
return await authenticate(false); return await authenticate(false);
} catch (e) { } catch (e) {
const status = e.response?.status; const status = e.cause?.status;
const networkErrorCodes = new Set([ const networkErrorCodes = new Set([
'ECONNREFUSED', 'ECONNREFUSED',
@@ -190,7 +190,7 @@ class JellyfinAPI extends ExternalAPI {
return systemInfoResponse; return systemInfoResponse;
} catch (e) { } catch (e) {
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken); throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
} }
} }
@@ -207,7 +207,7 @@ class JellyfinAPI extends ExternalAPI {
{ label: 'Jellyfin API' } { label: 'Jellyfin API' }
); );
throw new ApiError(e.response?.status, ApiErrorCode.Unknown); throw new ApiError(e.cause?.status, ApiErrorCode.Unknown);
} }
} }
@@ -222,7 +222,7 @@ class JellyfinAPI extends ExternalAPI {
{ label: 'Jellyfin API' } { label: 'Jellyfin API' }
); );
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken); throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
} }
} }
@@ -238,7 +238,7 @@ class JellyfinAPI extends ExternalAPI {
{ label: 'Jellyfin API' } { label: 'Jellyfin API' }
); );
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken); throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
} }
} }
@@ -317,7 +317,7 @@ class JellyfinAPI extends ExternalAPI {
{ label: 'Jellyfin API' } { label: 'Jellyfin API' }
); );
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken); throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
} }
} }
@@ -338,7 +338,7 @@ class JellyfinAPI extends ExternalAPI {
{ label: 'Jellyfin API' } { label: 'Jellyfin API' }
); );
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken); throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
} }
} }
@@ -353,7 +353,7 @@ class JellyfinAPI extends ExternalAPI {
return itemResponse; return itemResponse;
} catch (e) { } catch (e) {
if (availabilitySync.running) { if (availabilitySync.running) {
if (e.response && e.response.status === 500) { if (e.cause?.status === 500) {
return undefined; return undefined;
} }
} }
@@ -362,7 +362,7 @@ class JellyfinAPI extends ExternalAPI {
`Something went wrong while getting library content from the Jellyfin server: ${e.message}`, `Something went wrong while getting library content from the Jellyfin server: ${e.message}`,
{ label: 'Jellyfin API' } { label: 'Jellyfin API' }
); );
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken); throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
} }
} }
@@ -377,7 +377,7 @@ class JellyfinAPI extends ExternalAPI {
{ label: 'Jellyfin API' } { label: 'Jellyfin API' }
); );
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken); throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
} }
} }
@@ -402,7 +402,7 @@ class JellyfinAPI extends ExternalAPI {
{ label: 'Jellyfin API' } { label: 'Jellyfin API' }
); );
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken); throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
} }
} }
} }

View File

@@ -179,13 +179,20 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
} }
return data; return data;
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error( logger.error(
'Failed to add movie to Radarr. This might happen if the movie already exists, in which case you can safely ignore this error.', 'Failed to add movie to Radarr. This might happen if the movie already exists, in which case you can safely ignore this error.',
{ {
label: 'Radarr', label: 'Radarr',
errorMessage: e.message, errorMessage: e.message,
options, options,
response: e?.response?.data, response: errorData,
} }
); );
throw new Error('Failed to add movie to Radarr'); throw new Error('Failed to add movie to Radarr');

View File

@@ -257,11 +257,18 @@ class SonarrAPI extends ServarrBase<{
return createdSeriesData; return createdSeriesData;
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Something went wrong while adding a series to Sonarr.', { logger.error('Something went wrong while adding a series to Sonarr.', {
label: 'Sonarr API', label: 'Sonarr API',
errorMessage: e.message, errorMessage: e.message,
options, options,
response: e?.response?.data, response: errorData,
}); });
throw new Error('Failed to add series'); throw new Error('Failed to add series');
} }

View File

@@ -291,7 +291,7 @@ class DiscordAgent
} }
} }
await fetch(settings.options.webhookUrl, { const response = await fetch(settings.options.webhookUrl, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -305,15 +305,25 @@ class DiscordAgent
content: userMentions.join(' '), content: userMentions.join(' '),
} as DiscordWebhookPayload), } as DiscordWebhookPayload),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
return true; return true;
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Discord notification', { logger.error('Error sending Discord notification', {
label: 'Notifications', label: 'Notifications',
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;

View File

@@ -132,22 +132,32 @@ class GotifyAgent
const endpoint = `${settings.options.url}/message?token=${settings.options.token}`; const endpoint = `${settings.options.url}/message?token=${settings.options.token}`;
const notificationPayload = this.getNotificationPayload(type, payload); const notificationPayload = this.getNotificationPayload(type, payload);
await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify(notificationPayload), body: JSON.stringify(notificationPayload),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
return true; return true;
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Gotify notification', { logger.error('Error sending Gotify notification', {
label: 'Notifications', label: 'Notifications',
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;

View File

@@ -100,7 +100,7 @@ class LunaSeaAgent
}); });
try { try {
await fetch(settings.options.webhookUrl, { const response = await fetch(settings.options.webhookUrl, {
method: 'POST', method: 'POST',
headers: settings.options.profileName headers: settings.options.profileName
? { ? {
@@ -114,15 +114,25 @@ class LunaSeaAgent
}, },
body: JSON.stringify(this.buildPayload(type, payload)), body: JSON.stringify(this.buildPayload(type, payload)),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
return true; return true;
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending LunaSea notification', { logger.error('Error sending LunaSea notification', {
label: 'Notifications', label: 'Notifications',
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;

View File

@@ -122,7 +122,7 @@ class PushbulletAgent
}); });
try { try {
await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -133,13 +133,23 @@ class PushbulletAgent
channel_tag: settings.options.channelTag, channel_tag: settings.options.channelTag,
}), }),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Pushbullet notification', { logger.error('Error sending Pushbullet notification', {
label: 'Notifications', label: 'Notifications',
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;
@@ -164,7 +174,7 @@ class PushbulletAgent
}); });
try { try {
await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -172,14 +182,24 @@ class PushbulletAgent
}, },
body: JSON.stringify(notificationPayload), body: JSON.stringify(notificationPayload),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Pushbullet notification', { logger.error('Error sending Pushbullet notification', {
label: 'Notifications', label: 'Notifications',
recipient: payload.notifyUser.displayName, recipient: payload.notifyUser.displayName,
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;
@@ -215,7 +235,7 @@ class PushbulletAgent
}); });
try { try {
await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -223,14 +243,24 @@ class PushbulletAgent
}, },
body: JSON.stringify(notificationPayload), body: JSON.stringify(notificationPayload),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Pushbullet notification', { logger.error('Error sending Pushbullet notification', {
label: 'Notifications', label: 'Notifications',
recipient: user.displayName, recipient: user.displayName,
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;

View File

@@ -52,6 +52,9 @@ class PushoverAgent
): Promise<Partial<PushoverImagePayload>> { ): Promise<Partial<PushoverImagePayload>> {
try { try {
const response = await fetch(imageUrl); const response = await fetch(imageUrl);
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
const arrayBuffer = await response.arrayBuffer(); const arrayBuffer = await response.arrayBuffer();
const base64 = Buffer.from(arrayBuffer).toString('base64'); const base64 = Buffer.from(arrayBuffer).toString('base64');
const contentType = ( const contentType = (
@@ -64,10 +67,17 @@ class PushoverAgent
attachment_type: contentType, attachment_type: contentType,
}; };
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error getting image payload', { logger.error('Error getting image payload', {
label: 'Notifications', label: 'Notifications',
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return {}; return {};
} }
@@ -200,7 +210,7 @@ class PushoverAgent
}); });
try { try {
await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -212,13 +222,23 @@ class PushoverAgent
sound: settings.options.sound, sound: settings.options.sound,
} as PushoverPayload), } as PushoverPayload),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Pushover notification', { logger.error('Error sending Pushover notification', {
label: 'Notifications', label: 'Notifications',
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;
@@ -246,7 +266,7 @@ class PushoverAgent
}); });
try { try {
await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -258,14 +278,24 @@ class PushoverAgent
sound: payload.notifyUser.settings.pushoverSound, sound: payload.notifyUser.settings.pushoverSound,
} as PushoverPayload), } as PushoverPayload),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Pushover notification', { logger.error('Error sending Pushover notification', {
label: 'Notifications', label: 'Notifications',
recipient: payload.notifyUser.displayName, recipient: payload.notifyUser.displayName,
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;
@@ -302,7 +332,7 @@ class PushoverAgent
}); });
try { try {
await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -313,14 +343,24 @@ class PushoverAgent
user: user.settings.pushoverUserKey, user: user.settings.pushoverUserKey,
} as PushoverPayload), } as PushoverPayload),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Pushover notification', { logger.error('Error sending Pushover notification', {
label: 'Notifications', label: 'Notifications',
recipient: user.displayName, recipient: user.displayName,
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;

View File

@@ -237,22 +237,32 @@ class SlackAgent
subject: payload.subject, subject: payload.subject,
}); });
try { try {
await fetch(settings.options.webhookUrl, { const response = await fetch(settings.options.webhookUrl, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify(this.buildEmbed(type, payload)), body: JSON.stringify(this.buildEmbed(type, payload)),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
return true; return true;
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Slack notification', { logger.error('Error sending Slack notification', {
label: 'Notifications', label: 'Notifications',
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;

View File

@@ -174,7 +174,7 @@ class TelegramAgent
}); });
try { try {
await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -185,13 +185,23 @@ class TelegramAgent
disable_notification: !!settings.options.sendSilently, disable_notification: !!settings.options.sendSilently,
} as TelegramMessagePayload | TelegramPhotoPayload), } as TelegramMessagePayload | TelegramPhotoPayload),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Telegram notification', { logger.error('Error sending Telegram notification', {
label: 'Notifications', label: 'Notifications',
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;
@@ -215,7 +225,7 @@ class TelegramAgent
}); });
try { try {
await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -227,14 +237,24 @@ class TelegramAgent
!!payload.notifyUser.settings.telegramSendSilently, !!payload.notifyUser.settings.telegramSendSilently,
} as TelegramMessagePayload | TelegramPhotoPayload), } as TelegramMessagePayload | TelegramPhotoPayload),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Telegram notification', { logger.error('Error sending Telegram notification', {
label: 'Notifications', label: 'Notifications',
recipient: payload.notifyUser.displayName, recipient: payload.notifyUser.displayName,
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;
@@ -268,7 +288,7 @@ class TelegramAgent
}); });
try { try {
await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -279,14 +299,24 @@ class TelegramAgent
disable_notification: !!user.settings?.telegramSendSilently, disable_notification: !!user.settings?.telegramSendSilently,
} as TelegramMessagePayload | TelegramPhotoPayload), } as TelegramMessagePayload | TelegramPhotoPayload),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending Telegram notification', { logger.error('Error sending Telegram notification', {
label: 'Notifications', label: 'Notifications',
recipient: user.displayName, recipient: user.displayName,
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;

View File

@@ -177,7 +177,7 @@ class WebhookAgent
}); });
try { try {
await fetch(settings.options.webhookUrl, { const response = await fetch(settings.options.webhookUrl, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -187,15 +187,25 @@ class WebhookAgent
}, },
body: JSON.stringify(this.buildPayload(type, payload)), body: JSON.stringify(this.buildPayload(type, payload)),
}); });
if (!response.ok) {
throw new Error(response.statusText, { cause: response });
}
return true; return true;
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Error sending webhook notification', { logger.error('Error sending webhook notification', {
label: 'Notifications', label: 'Notifications',
type: Notification[type], type: Notification[type],
subject: payload.subject, subject: payload.subject,
errorMessage: e.message, errorMessage: e.message,
response: e.response?.data, response: errorData,
}); });
return false; return false;

View File

@@ -119,10 +119,17 @@ const JellyfinLogin: React.FC<JellyfinLoginProps> = ({
email: values.email, email: values.email,
}), }),
}); });
if (!res.ok) throw new Error(); if (!res.ok) throw new Error(res.statusText, { cause: res });
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
let errorMessage = null; let errorMessage = null;
switch (e.response?.data?.message) { switch (errorData?.message) {
case ApiErrorCode.InvalidUrl: case ApiErrorCode.InvalidUrl:
errorMessage = messages.invalidurlerror; errorMessage = messages.invalidurlerror;
break; break;

View File

@@ -50,14 +50,21 @@ const Login = () => {
}, },
body: JSON.stringify({ authToken }), body: JSON.stringify({ authToken }),
}); });
if (!res.ok) throw new Error(); if (!res.ok) throw new Error(res.statusText, { cause: res });
const data = await res.json(); const data = await res.json();
if (data?.id) { if (data?.id) {
revalidate(); revalidate();
} }
} catch (e) { } catch (e) {
setError(e.response.data.message); let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
setError(errorData?.message);
setAuthToken(undefined); setAuthToken(undefined);
setProcessing(false); setProcessing(false);
} }

View File

@@ -173,11 +173,18 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
const res = await fetch( const res = await fetch(
`/api/v1/settings/jellyfin/library?${searchParams.toString()}` `/api/v1/settings/jellyfin/library?${searchParams.toString()}`
); );
if (!res.ok) throw new Error(); if (!res.ok) throw new Error(res.statusText, { cause: res });
setIsSyncing(false); setIsSyncing(false);
revalidate(); revalidate();
} catch (e) { } catch (e) {
if (e.response.data.message === 'SYNC_ERROR_GROUPED_FOLDERS') { let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
if (errorData?.message === 'SYNC_ERROR_GROUPED_FOLDERS') {
toasts.addToast( toasts.addToast(
intl.formatMessage( intl.formatMessage(
messages.jellyfinSyncFailedAutomaticGroupedFolders messages.jellyfinSyncFailedAutomaticGroupedFolders
@@ -187,7 +194,7 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
appearance: 'warning', appearance: 'warning',
} }
); );
} else if (e.response.data.message === 'SYNC_ERROR_NO_LIBRARIES') { } else if (errorData?.message === 'SYNC_ERROR_NO_LIBRARIES') {
toasts.addToast( toasts.addToast(
intl.formatMessage(messages.jellyfinSyncFailedNoLibrariesFound), intl.formatMessage(messages.jellyfinSyncFailedNoLibrariesFound),
{ {
@@ -485,7 +492,7 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
jellyfinForgotPasswordUrl: values.jellyfinForgotPasswordUrl, jellyfinForgotPasswordUrl: values.jellyfinForgotPasswordUrl,
} as JellyfinSettings), } as JellyfinSettings),
}); });
if (!res.ok) throw new Error(); if (!res.ok) throw new Error(res.statusText, { cause: res });
addToast( addToast(
intl.formatMessage(messages.jellyfinSettingsSuccess, { intl.formatMessage(messages.jellyfinSettingsSuccess, {
@@ -500,7 +507,14 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
} }
); );
} catch (e) { } catch (e) {
if (e.response?.data?.message === ApiErrorCode.InvalidUrl) { let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
if (errorData?.message === ApiErrorCode.InvalidUrl) {
addToast( addToast(
intl.formatMessage(messages.invalidurlerror, { intl.formatMessage(messages.invalidurlerror, {
mediaServerName: mediaServerName:

View File

@@ -295,16 +295,23 @@ const UserList = () => {
password: values.genpassword ? null : values.password, password: values.genpassword ? null : values.password,
}), }),
}); });
if (!res.ok) throw new Error(); if (!res.ok) throw new Error(res.statusText, { cause: res });
addToast(intl.formatMessage(messages.usercreatedsuccess), { addToast(intl.formatMessage(messages.usercreatedsuccess), {
appearance: 'success', appearance: 'success',
autoDismiss: true, autoDismiss: true,
}); });
setCreateModal({ isOpen: false }); setCreateModal({ isOpen: false });
} catch (e) { } catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
addToast( addToast(
intl.formatMessage( intl.formatMessage(
e.response.data.errors?.includes('USER_EXISTS') errorData.errors?.includes('USER_EXISTS')
? messages.usercreatedfailedexisting ? messages.usercreatedfailedexisting
: messages.usercreatedfailed : messages.usercreatedfailed
), ),