Improve error handling during group sends
This commit is contained in:
parent
f0a3735ca2
commit
991580a1ed
58 changed files with 299 additions and 324 deletions
|
@ -13,27 +13,28 @@ let quitText = 'Quit';
|
|||
let copyErrorAndQuitText = 'Copy error and quit';
|
||||
|
||||
function handleError(prefix: string, error: Error): void {
|
||||
const formattedError = Errors.toLogFormat(error);
|
||||
if (console._error) {
|
||||
console._error(`${prefix}:`, Errors.toLogFormat(error));
|
||||
console._error(`${prefix}:`, formattedError);
|
||||
}
|
||||
console.error(`${prefix}:`, Errors.toLogFormat(error));
|
||||
console.error(`${prefix}:`, formattedError);
|
||||
|
||||
if (app.isReady()) {
|
||||
// title field is not shown on macOS, so we don't use it
|
||||
const buttonIndex = dialog.showMessageBoxSync({
|
||||
buttons: [quitText, copyErrorAndQuitText],
|
||||
defaultId: 0,
|
||||
detail: redactAll(error.stack || ''),
|
||||
detail: redactAll(formattedError),
|
||||
message: prefix,
|
||||
noLink: true,
|
||||
type: 'error',
|
||||
});
|
||||
|
||||
if (buttonIndex === 1) {
|
||||
clipboard.writeText(`${prefix}\n\n${redactAll(error.stack || '')}`);
|
||||
clipboard.writeText(`${prefix}\n\n${redactAll(formattedError)}`);
|
||||
}
|
||||
} else {
|
||||
dialog.showErrorBox(prefix, error.stack || '');
|
||||
dialog.showErrorBox(prefix, formattedError);
|
||||
}
|
||||
|
||||
app.exit(1);
|
||||
|
|
32
app/main.ts
32
app/main.ts
|
@ -46,6 +46,7 @@ import { strictAssert } from '../ts/util/assert';
|
|||
import { consoleLogger } from '../ts/util/consoleLogger';
|
||||
import type { ThemeSettingType } from '../ts/types/StorageUIKeys';
|
||||
import { ThemeType } from '../ts/types/Util';
|
||||
import * as Errors from '../ts/types/errors';
|
||||
|
||||
import './startup_config';
|
||||
|
||||
|
@ -471,7 +472,7 @@ async function handleUrl(event: Electron.Event, rawTarget: string) {
|
|||
try {
|
||||
await shell.openExternal(target);
|
||||
} catch (error) {
|
||||
getLogger().error(`Failed to open url: ${error.stack}`);
|
||||
getLogger().error(`Failed to open url: ${Errors.toLogFormat(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -938,7 +939,7 @@ ipc.handle('database-ready', async () => {
|
|||
if (error) {
|
||||
getLogger().error(
|
||||
'database-ready requested, but got sql error',
|
||||
error && error.stack
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -1029,7 +1030,7 @@ async function readyForUpdates() {
|
|||
} catch (error) {
|
||||
getLogger().error(
|
||||
'Error starting update checks:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1039,10 +1040,7 @@ async function forceUpdate() {
|
|||
getLogger().info('starting force update');
|
||||
await updater.force();
|
||||
} catch (error) {
|
||||
getLogger().error(
|
||||
'Error during force update:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
getLogger().error('Error during force update:', Errors.toLogFormat(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1477,7 +1475,7 @@ const runSQLCorruptionHandler = async () => {
|
|||
`Restarting the application immediately. Error: ${error.message}`
|
||||
);
|
||||
|
||||
await onDatabaseError(error.stack || error.message);
|
||||
await onDatabaseError(Errors.toLogFormat(error));
|
||||
};
|
||||
|
||||
async function initializeSQL(
|
||||
|
@ -1796,7 +1794,7 @@ app.on('ready', async () => {
|
|||
} catch (err) {
|
||||
logger.error(
|
||||
'main/ready: Error deleting temp dir:',
|
||||
err && err.stack ? err.stack : err
|
||||
Errors.toLogFormat(err)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1823,7 +1821,7 @@ app.on('ready', async () => {
|
|||
if (sqlError) {
|
||||
getLogger().error('sql.initialize was unsuccessful; returning early');
|
||||
|
||||
await onDatabaseError(sqlError.stack || sqlError.message);
|
||||
await onDatabaseError(Errors.toLogFormat(sqlError));
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1840,7 +1838,7 @@ app.on('ready', async () => {
|
|||
} catch (err) {
|
||||
getLogger().error(
|
||||
'(ready event handler) error deleting IndexedDB:',
|
||||
err && err.stack ? err.stack : err
|
||||
Errors.toLogFormat(err)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1949,10 +1947,7 @@ async function requestShutdown() {
|
|||
try {
|
||||
await request;
|
||||
} catch (error) {
|
||||
getLogger().error(
|
||||
'requestShutdown error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
getLogger().error('requestShutdown error:', Errors.toLogFormat(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2157,7 +2152,7 @@ ipc.handle(
|
|||
} catch (error) {
|
||||
getLogger().error(
|
||||
'show-permissions-popup error:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2200,7 +2195,10 @@ ipc.on('get-built-in-images', async () => {
|
|||
if (mainWindow && mainWindow.webContents) {
|
||||
mainWindow.webContents.send('get-success-built-in-images', error.message);
|
||||
} else {
|
||||
getLogger().error('Error handling get-built-in-images:', error.stack);
|
||||
getLogger().error(
|
||||
'Error handling get-built-in-images:',
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@ import { app } from 'electron';
|
|||
|
||||
import { start } from './base_config';
|
||||
import config from './config';
|
||||
import * as Errors from '../ts/types/errors';
|
||||
|
||||
let userData: string | undefined;
|
||||
// Use separate data directory for benchmarks & development
|
||||
|
@ -23,7 +24,7 @@ if (userData !== undefined) {
|
|||
try {
|
||||
mkdirSync(userData, { recursive: true });
|
||||
} catch (error) {
|
||||
console.error('Failed to create userData', error?.stack || String(error));
|
||||
console.error('Failed to create userData', Errors.toLogFormat(error));
|
||||
}
|
||||
|
||||
app.setPath('userData', userData);
|
||||
|
|
|
@ -13,7 +13,9 @@ import type { Props as DropZoneProps } from '../elements/DropZone';
|
|||
import { DropZone } from '../elements/DropZone';
|
||||
import { processStickerImage } from '../util/preload';
|
||||
import { useI18n } from '../util/i18n';
|
||||
import { ProcessStickerImageError } from '../errors';
|
||||
import { MINUTE } from '../../ts/util/durations';
|
||||
import * as Errors from '../../ts/types/errors';
|
||||
|
||||
const queue = new PQueue({ concurrency: 3, timeout: MINUTE * 30 });
|
||||
|
||||
|
@ -64,13 +66,16 @@ const InnerGrid = SortableContainer(
|
|||
} catch (e) {
|
||||
window.SignalContext.log.error(
|
||||
'Error processing image:',
|
||||
e?.stack ? e.stack : String(e)
|
||||
Errors.toLogFormat(e)
|
||||
);
|
||||
actions.removeSticker(path);
|
||||
|
||||
const key =
|
||||
e instanceof ProcessStickerImageError
|
||||
? e.errorMessageI18nKey
|
||||
: 'StickerCreator--Toasts--errorProcessing';
|
||||
actions.addToast({
|
||||
key:
|
||||
(e || {}).errorMessageI18nKey ||
|
||||
'StickerCreator--Toasts--errorProcessing',
|
||||
key,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
8
sticker-creator/errors.ts
Normal file
8
sticker-creator/errors.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
export class ProcessStickerImageError extends Error {
|
||||
constructor(message: string, public readonly errorMessageI18nKey: string) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ import { initialize as initializeWebAPI } from '../../ts/textsecure/WebAPI';
|
|||
|
||||
import { SignalContext } from '../../ts/windows/context';
|
||||
import { getAnimatedPngDataIfExists } from '../../ts/util/getAnimatedPngDataIfExists';
|
||||
import { ProcessStickerImageError } from '../errors';
|
||||
|
||||
const STICKER_SIZE = 512;
|
||||
const MIN_STICKER_DIMENSION = 10;
|
||||
|
@ -42,12 +43,6 @@ const WebAPI = initializeWebAPI({
|
|||
version: config.version,
|
||||
});
|
||||
|
||||
function processStickerError(message: string, i18nKey: string): Error {
|
||||
const result = new Error(message);
|
||||
result.errorMessageI18nKey = i18nKey;
|
||||
return result;
|
||||
}
|
||||
|
||||
window.processStickerImage = async (path: string | undefined) => {
|
||||
if (!path) {
|
||||
throw new Error(`Path ${path} is not valid!`);
|
||||
|
@ -59,7 +54,7 @@ window.processStickerImage = async (path: string | undefined) => {
|
|||
|
||||
const { width, height } = meta;
|
||||
if (!width || !height) {
|
||||
throw processStickerError(
|
||||
throw new ProcessStickerImageError(
|
||||
'Sticker height or width were falsy',
|
||||
'StickerCreator--Toasts--errorProcessing'
|
||||
);
|
||||
|
@ -75,31 +70,31 @@ window.processStickerImage = async (path: string | undefined) => {
|
|||
const animatedPngDataIfExists = getAnimatedPngDataIfExists(imgBuffer);
|
||||
if (animatedPngDataIfExists) {
|
||||
if (imgBuffer.byteLength > MAX_STICKER_BYTE_LENGTH) {
|
||||
throw processStickerError(
|
||||
throw new ProcessStickerImageError(
|
||||
'Sticker file was too large',
|
||||
'StickerCreator--Toasts--tooLarge'
|
||||
);
|
||||
}
|
||||
if (width !== height) {
|
||||
throw processStickerError(
|
||||
throw new ProcessStickerImageError(
|
||||
'Sticker must be square',
|
||||
'StickerCreator--Toasts--APNG--notSquare'
|
||||
);
|
||||
}
|
||||
if (width > MAX_STICKER_DIMENSION) {
|
||||
throw processStickerError(
|
||||
throw new ProcessStickerImageError(
|
||||
'Sticker dimensions are too large',
|
||||
'StickerCreator--Toasts--APNG--dimensionsTooLarge'
|
||||
);
|
||||
}
|
||||
if (width < MIN_STICKER_DIMENSION) {
|
||||
throw processStickerError(
|
||||
throw new ProcessStickerImageError(
|
||||
'Sticker dimensions are too small',
|
||||
'StickerCreator--Toasts--APNG--dimensionsTooSmall'
|
||||
);
|
||||
}
|
||||
if (animatedPngDataIfExists.numPlays !== Infinity) {
|
||||
throw processStickerError(
|
||||
throw new ProcessStickerImageError(
|
||||
'Animated stickers must loop forever',
|
||||
'StickerCreator--Toasts--mustLoopForever'
|
||||
);
|
||||
|
@ -118,7 +113,7 @@ window.processStickerImage = async (path: string | undefined) => {
|
|||
.webp()
|
||||
.toBuffer();
|
||||
if (processedBuffer.byteLength > MAX_STICKER_BYTE_LENGTH) {
|
||||
throw processStickerError(
|
||||
throw new ProcessStickerImageError(
|
||||
'Sticker file was too large',
|
||||
'StickerCreator--Toasts--tooLarge'
|
||||
);
|
||||
|
|
|
@ -299,7 +299,7 @@ export class ConversationController {
|
|||
log.error(
|
||||
'Contact is not valid. Not saving, but adding to collection:',
|
||||
conversation.idForLogging(),
|
||||
validationError.stack
|
||||
Errors.toLogFormat(validationError)
|
||||
);
|
||||
|
||||
return conversation;
|
||||
|
@ -316,7 +316,7 @@ export class ConversationController {
|
|||
identifier,
|
||||
type,
|
||||
'Error:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
@ -1247,7 +1247,7 @@ export class ConversationController {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'ConversationController.load/map: Failed to prepare a conversation',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
})
|
||||
|
@ -1256,7 +1256,7 @@ export class ConversationController {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'ConversationController: initial fetch failed',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
|
|
@ -392,7 +392,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'removePreKey error triggering removePreKey:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -604,7 +604,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
await this.commitZoneChanges('saveSenderKey');
|
||||
}
|
||||
} catch (error) {
|
||||
const errorString = error && error.stack ? error.stack : error;
|
||||
const errorString = Errors.toLogFormat(error);
|
||||
log.error(
|
||||
`saveSenderKey: failed to save senderKey ${senderId}/${distributionId}: ${errorString}`
|
||||
);
|
||||
|
@ -653,7 +653,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
log.info('Successfully fetched sender key(cache miss):', id);
|
||||
return item;
|
||||
} catch (error) {
|
||||
const errorString = error && error.stack ? error.stack : error;
|
||||
const errorString = Errors.toLogFormat(error);
|
||||
log.error(
|
||||
`getSenderKey: failed to load sender key ${senderId}/${distributionId}: ${errorString}`
|
||||
);
|
||||
|
@ -679,7 +679,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
|
||||
this.senderKeys.delete(id);
|
||||
} catch (error) {
|
||||
const errorString = error && error.stack ? error.stack : error;
|
||||
const errorString = Errors.toLogFormat(error);
|
||||
log.error(
|
||||
`removeSenderKey: failed to remove senderKey ${senderId}/${distributionId}: ${errorString}`
|
||||
);
|
||||
|
@ -860,7 +860,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
`pending sender keys size ${this.pendingSenderKeys.size}, ` +
|
||||
`pending sessions size ${this.pendingSessions.size}, ` +
|
||||
`pending unprocessed size ${this.pendingUnprocessed.size}`,
|
||||
error && error.stack
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
this.pendingSenderKeys.clear();
|
||||
this.pendingSessions.clear();
|
||||
|
@ -961,7 +961,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
// and save it to the database.
|
||||
return await this._maybeMigrateSession(entry.fromDB, { zone });
|
||||
} catch (error) {
|
||||
const errorString = error && error.stack ? error.stack : error;
|
||||
const errorString = Errors.toLogFormat(error);
|
||||
log.error(`loadSession: failed to load session ${id}: ${errorString}`);
|
||||
return undefined;
|
||||
}
|
||||
|
@ -1095,7 +1095,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
await this.commitZoneChanges('storeSession');
|
||||
}
|
||||
} catch (error) {
|
||||
const errorString = error && error.stack ? error.stack : error;
|
||||
const errorString = Errors.toLogFormat(error);
|
||||
log.error(`storeSession: Save failed for ${id}: ${errorString}`);
|
||||
throw error;
|
||||
}
|
||||
|
@ -1189,7 +1189,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'getOpenDevices: Failed to get devices',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
@ -1692,7 +1692,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'saveIdentity: error triggering keychange:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -609,7 +609,7 @@ export async function startApp(): Promise<void> {
|
|||
} catch (error) {
|
||||
log.info(
|
||||
'User chose not to delete old data. Shutting down.',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
window.shutdown();
|
||||
return;
|
||||
|
@ -627,7 +627,7 @@ export async function startApp(): Promise<void> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'Failed to remove IndexedDB file or remove SQL data:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -859,7 +859,7 @@ export async function startApp(): Promise<void> {
|
|||
try {
|
||||
await window.Signal.Data.startInRendererProcess();
|
||||
} catch (err) {
|
||||
log.error('SQL failed to initialize', err && err.stack ? err.stack : err);
|
||||
log.error('SQL failed to initialize', Errors.toLogFormat(err));
|
||||
}
|
||||
|
||||
setAppLoadingScreenMessage(window.i18n('loading'), window.i18n);
|
||||
|
@ -950,7 +950,7 @@ export async function startApp(): Promise<void> {
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
'background/setInterval: Failed to parse integer from desktop.retryRespondMaxAge feature flag',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -961,7 +961,7 @@ export async function startApp(): Promise<void> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'background/onready/setInterval: Error deleting sent protos: ',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -991,7 +991,7 @@ export async function startApp(): Promise<void> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'background/onready/setInterval: Error getting expired retry placeholders: ',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}, FIVE_MINUTES);
|
||||
|
@ -1038,7 +1038,7 @@ export async function startApp(): Promise<void> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'background.js: ConversationController failed to load:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
} finally {
|
||||
initializeRedux({ mainWindowStats, menuOptions });
|
||||
|
@ -2140,7 +2140,7 @@ export async function startApp(): Promise<void> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'connect: Error refreshing remote config:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2226,7 +2226,7 @@ export async function startApp(): Promise<void> {
|
|||
} catch (e) {
|
||||
log.error(
|
||||
'Problem with account manager updates after starting new version: ',
|
||||
e && e.stack ? e.stack : e
|
||||
Errors.toLogFormat(e)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2239,7 +2239,7 @@ export async function startApp(): Promise<void> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'Error: Unable to register for unauthenticated delivery support.',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2270,7 +2270,7 @@ export async function startApp(): Promise<void> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'Error: Unable to register our capabilities.',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2859,7 +2859,10 @@ export async function startApp(): Promise<void> {
|
|||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
log.error('respondWithProfileKeyBatcher error', error && error.stack);
|
||||
log.error(
|
||||
'respondWithProfileKeyBatcher error',
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
sender.queueJob('sendProfileKeyUpdate', () =>
|
||||
|
@ -3521,7 +3524,7 @@ export async function startApp(): Promise<void> {
|
|||
log.error(
|
||||
'unlinkAndDisconnect: Something went wrong clearing ' +
|
||||
'local configuration',
|
||||
eraseError && eraseError.stack ? eraseError.stack : eraseError
|
||||
Errors.toLogFormat(eraseError)
|
||||
);
|
||||
} finally {
|
||||
window.Signal.Util.Registration.markEverDone();
|
||||
|
|
|
@ -15,6 +15,7 @@ import type { ExecuteMenuRoleType } from './TitleBarContainer';
|
|||
import { ToastLoadingFullLogs } from './ToastLoadingFullLogs';
|
||||
import { openLinkInWebBrowser } from '../util/openLinkInWebBrowser';
|
||||
import { createSupportUrl } from '../util/createSupportUrl';
|
||||
import * as Errors from '../types/errors';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
import { useTheme } from '../hooks/useTheme';
|
||||
|
||||
|
@ -107,10 +108,7 @@ export function DebugLogWindow({
|
|||
const publishedLogURL = await uploadLogs(text);
|
||||
setPublicLogURL(publishedLogURL);
|
||||
} catch (error) {
|
||||
log.error(
|
||||
'DebugLogWindow error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('DebugLogWindow error:', Errors.toLogFormat(error));
|
||||
setLoadState(LoadState.Loaded);
|
||||
setToastType(ToastType.Error);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
getImageDimensions,
|
||||
defaultBlurHash,
|
||||
} from '../../types/Attachment';
|
||||
import * as Errors from '../../types/errors';
|
||||
import * as log from '../../logging/log';
|
||||
|
||||
const MAX_GIF_REPEAT = 4;
|
||||
|
@ -90,7 +91,7 @@ export function GIF(props: Props): JSX.Element {
|
|||
video.play().catch(error => {
|
||||
log.info(
|
||||
"Failed to match GIF playback to window's state",
|
||||
(error && error.stack) || error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
});
|
||||
} else {
|
||||
|
|
53
ts/groups.ts
53
ts/groups.ts
|
@ -453,7 +453,10 @@ async function uploadAvatar(
|
|||
key,
|
||||
};
|
||||
} catch (error) {
|
||||
log.warn(`uploadAvatar/${logId} Failed to upload avatar`, error.stack);
|
||||
log.warn(
|
||||
`uploadAvatar/${logId} Failed to upload avatar`,
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
@ -2391,7 +2394,7 @@ export async function initiateMigrationToGroupV2(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`initiateMigrationToGroupV2/${logId}: Error creating group:`,
|
||||
error.stack
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
|
||||
throw error;
|
||||
|
@ -2473,7 +2476,7 @@ export async function waitThenRespondToGroupV2Migration(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`waitThenRespondToGroupV2Migration/${conversation.idForLogging()}: respondToGroupV2Migration failure:`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -2946,7 +2949,7 @@ export async function waitThenMaybeUpdateGroup(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`waitThenMaybeUpdateGroup/${conversation.idForLogging()}: maybeUpdateGroup failure:`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -2984,7 +2987,7 @@ export async function maybeUpdateGroup(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`maybeUpdateGroup/${logId}: Failed to update group:`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
@ -3910,7 +3913,7 @@ async function integrateGroupChanges({
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`integrateGroupChanges/${logId}: Failed to apply change log, continuing to apply remaining change logs.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -5287,7 +5290,7 @@ export async function applyNewAvatar(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`applyNewAvatar/${logId} Failed to handle avatar, clearing it`,
|
||||
error.stack
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
if (result.avatar && result.avatar.path) {
|
||||
await window.Signal.Migrations.deleteAttachmentData(result.avatar.path);
|
||||
|
@ -5622,7 +5625,7 @@ function decryptGroupChange(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupChange/${logId}: Unable to decrypt sourceUuid.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5677,7 +5680,7 @@ function decryptGroupChange(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupChange/${logId}: Unable to decrypt deleteMembers.deletedUserId. Dropping member.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
@ -5711,7 +5714,7 @@ function decryptGroupChange(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupChange/${logId}: Unable to decrypt modifyMemberRole.userId. Dropping member.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
@ -5844,7 +5847,7 @@ function decryptGroupChange(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupChange/${logId}: Unable to decrypt deletePendingMembers.deletedUserId. Dropping member.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
@ -6022,7 +6025,7 @@ function decryptGroupChange(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupChange/${logId}: Unable to decrypt modifyTitle.title`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -6049,7 +6052,7 @@ function decryptGroupChange(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupChange/${logId}: Unable to decrypt modifyDisappearingMessagesTimer.timer`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -6152,7 +6155,7 @@ function decryptGroupChange(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupChange/${logId}: Unable to decrypt deletePendingApproval.deletedUserId. Dropping member.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
@ -6190,7 +6193,7 @@ function decryptGroupChange(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupChange/${logId}: Unable to decrypt promoteAdminApproval.userId. Dropping member.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
@ -6232,7 +6235,7 @@ function decryptGroupChange(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupChange/${logId}: Unable to decrypt modifyDescription.descriptionBytes`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -6365,7 +6368,7 @@ function decryptGroupState(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupState/${logId}: Unable to decrypt title. Clearing it.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6388,7 +6391,7 @@ function decryptGroupState(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupState/${logId}: Unable to decrypt disappearing message timer. Clearing it.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6472,7 +6475,7 @@ function decryptGroupState(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptGroupState/${logId}: Unable to decrypt descriptionBytes. Clearing it.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6537,7 +6540,7 @@ function decryptMember(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptMember/${logId}: Unable to decrypt member userid. Dropping member.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
@ -6608,7 +6611,7 @@ function decryptMemberPendingProfileKey(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptMemberPendingProfileKey/${logId}: Unable to decrypt pending member addedByUserId. Dropping member.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
@ -6648,7 +6651,7 @@ function decryptMemberPendingProfileKey(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptMemberPendingProfileKey/${logId}: Unable to decrypt pending member userId. Dropping member.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
@ -6673,7 +6676,7 @@ function decryptMemberPendingProfileKey(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptMemberPendingProfileKey/${logId}: Unable to decrypt pending member profileKey. Dropping profileKey.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -6735,7 +6738,7 @@ function decryptMemberPendingAdminApproval(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptMemberPendingAdminApproval/${logId}: Unable to decrypt pending member userId. Dropping member.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
@ -6760,7 +6763,7 @@ function decryptMemberPendingAdminApproval(
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`decryptMemberPendingAdminApproval/${logId}: Unable to decrypt profileKey. Dropping profileKey.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import { read as readLastLines } from 'read-last-lines';
|
|||
import rimraf from 'rimraf';
|
||||
|
||||
import type { LoggerType } from '../types/Logging';
|
||||
import * as Errors from '../types/errors';
|
||||
import * as durations from '../util/durations';
|
||||
import { createRotatingPinoDest } from '../util/rotatingPinoDest';
|
||||
|
||||
|
@ -67,7 +68,9 @@ export async function initialize(
|
|||
try {
|
||||
await cleanupLogs(logPath);
|
||||
} catch (error) {
|
||||
const errorString = `Failed to clean logs; deleting all. Error: ${error.stack}`;
|
||||
const errorString =
|
||||
'Failed to clean logs; deleting all. ' +
|
||||
`Error: ${Errors.toLogFormat(error)}`;
|
||||
console.error(errorString);
|
||||
await deleteAllLogs(logPath);
|
||||
mkdirp.sync(logPath);
|
||||
|
@ -136,7 +139,7 @@ export async function initialize(
|
|||
...rest,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error(`Problem loading log data: ${error.stack}`);
|
||||
logger.error(`Problem loading log data: ${Errors.toLogFormat(error)}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -151,7 +154,7 @@ export async function initialize(
|
|||
try {
|
||||
await deleteAllLogs(logPath);
|
||||
} catch (error) {
|
||||
logger.error(`Problem deleting all logs: ${error.stack}`);
|
||||
logger.error(`Problem deleting all logs: ${Errors.toLogFormat(error)}`);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -196,7 +199,7 @@ async function cleanupLogs(logPath: string) {
|
|||
} catch (error) {
|
||||
console.error(
|
||||
'Error cleaning logs; deleting and starting over from scratch.',
|
||||
error.stack
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
|
||||
// delete and re-create the log directory
|
||||
|
@ -215,7 +218,7 @@ export function isLineAfterDate(line: string, date: Readonly<Date>): boolean {
|
|||
const data = JSON.parse(line);
|
||||
return new Date(data.time).getTime() > date.getTime();
|
||||
} catch (e) {
|
||||
console.log('error parsing log line', e.stack, line);
|
||||
console.log('error parsing log line', Errors.toLogFormat(e), line);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
} from './shared';
|
||||
import * as log from './log';
|
||||
import { Environment, getEnvironment } from '../environment';
|
||||
import * as Errors from '../types/errors';
|
||||
import { createRotatingPinoDest } from '../util/rotatingPinoDest';
|
||||
|
||||
// Backwards-compatible logging, simple strings and no level (defaulted to INFO)
|
||||
|
@ -114,14 +115,13 @@ window.SignalContext.log = {
|
|||
};
|
||||
|
||||
window.onerror = (_message, _script, _line, _col, error) => {
|
||||
const errorInfo = error && error.stack ? error.stack : JSON.stringify(error);
|
||||
const errorInfo = Errors.toLogFormat(error);
|
||||
log.error(`Top-level unhandled error: ${errorInfo}`);
|
||||
};
|
||||
|
||||
window.addEventListener('unhandledrejection', rejectionEvent => {
|
||||
const error = rejectionEvent.reason;
|
||||
const errorString =
|
||||
error && error.stack ? error.stack : JSON.stringify(error);
|
||||
const errorString = Errors.toLogFormat(error);
|
||||
log.error(`Top-level unhandled promise rejection: ${errorString}`);
|
||||
});
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import { Collection, Model } from 'backbone';
|
|||
import type { MessageModel } from '../models/messages';
|
||||
import { getContactId } from '../messages/helpers';
|
||||
import * as log from '../logging/log';
|
||||
import * as Errors from '../types/errors';
|
||||
import { deleteForEveryone } from '../util/deleteForEveryone';
|
||||
|
||||
export type DeleteAttributesType = {
|
||||
|
@ -97,10 +98,7 @@ export class Deletes extends Collection<DeleteModel> {
|
|||
this.remove(del);
|
||||
});
|
||||
} catch (error) {
|
||||
log.error(
|
||||
'Deletes.onDelete error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('Deletes.onDelete error:', Errors.toLogFormat(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import { getOwn } from '../util/getOwn';
|
|||
import { missingCaseError } from '../util/missingCaseError';
|
||||
import { createWaitBatcher } from '../util/waitBatcher';
|
||||
import type { UUIDStringType } from '../types/UUID';
|
||||
import * as Errors from '../types/errors';
|
||||
import {
|
||||
SendActionType,
|
||||
SendStatus,
|
||||
|
@ -331,10 +332,7 @@ export class MessageReceipts extends Collection<MessageReceiptModel> {
|
|||
|
||||
this.remove(receipt);
|
||||
} catch (error) {
|
||||
log.error(
|
||||
'MessageReceipts.onReceipt error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('MessageReceipts.onReceipt error:', Errors.toLogFormat(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import { Collection, Model } from 'backbone';
|
||||
import type { ConversationModel } from '../models/conversations';
|
||||
import * as log from '../logging/log';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
export type MessageRequestAttributesType = {
|
||||
threadE164?: string;
|
||||
|
@ -122,10 +123,7 @@ export class MessageRequests extends Collection<MessageRequestModel> {
|
|||
|
||||
this.remove(sync);
|
||||
} catch (error) {
|
||||
log.error(
|
||||
'MessageRequests.onResponse error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('MessageRequests.onResponse error:', Errors.toLogFormat(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import type {
|
|||
MessageAttributesType,
|
||||
ReactionAttributesType,
|
||||
} from '../model-types.d';
|
||||
import * as Errors from '../types/errors';
|
||||
import * as log from '../logging/log';
|
||||
import { getContactId, getContact } from '../messages/helpers';
|
||||
import { isDirectConversation, isMe } from '../util/whatTypeOfConversation';
|
||||
|
@ -213,10 +214,7 @@ export class Reactions extends Collection<ReactionModel> {
|
|||
this.remove(reaction);
|
||||
});
|
||||
} catch (error) {
|
||||
log.error(
|
||||
'Reactions.onReaction error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('Reactions.onReaction error:', Errors.toLogFormat(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import { isIncoming } from '../state/selectors/message';
|
|||
import { isMessageUnread } from '../util/isMessageUnread';
|
||||
import { notificationService } from '../services/notifications';
|
||||
import * as log from '../logging/log';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
export type ReadSyncAttributesType = {
|
||||
senderId: string;
|
||||
|
@ -142,10 +143,7 @@ export class ReadSyncs extends Collection {
|
|||
|
||||
this.remove(sync);
|
||||
} catch (error) {
|
||||
log.error(
|
||||
'ReadSyncs.onSync error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('ReadSyncs.onSync error:', Errors.toLogFormat(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import { Collection, Model } from 'backbone';
|
||||
import type { MessageModel } from '../models/messages';
|
||||
import * as log from '../logging/log';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
export type ViewOnceOpenSyncAttributesType = {
|
||||
source?: string;
|
||||
|
@ -94,10 +95,7 @@ export class ViewOnceOpenSyncs extends Collection<ViewOnceOpenSyncModel> {
|
|||
|
||||
this.remove(sync);
|
||||
} catch (error) {
|
||||
log.error(
|
||||
'ViewOnceOpenSyncs.onSync error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('ViewOnceOpenSyncs.onSync error:', Errors.toLogFormat(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import type { MessageModel } from '../models/messages';
|
|||
import { ReadStatus } from '../messages/MessageReadStatus';
|
||||
import { markViewed } from '../services/MessageUpdater';
|
||||
import { isDownloaded } from '../types/Attachment';
|
||||
import * as Errors from '../types/errors';
|
||||
import { isIncoming } from '../state/selectors/message';
|
||||
import { notificationService } from '../services/notifications';
|
||||
import { queueAttachmentDownloads } from '../util/queueAttachmentDownloads';
|
||||
|
@ -111,10 +112,7 @@ export class ViewSyncs extends Collection {
|
|||
|
||||
this.remove(sync);
|
||||
} catch (error) {
|
||||
log.error(
|
||||
'ViewSyncs.onSync error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('ViewSyncs.onSync error:', Errors.toLogFormat(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1242,7 +1242,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`Error erasing data for message ${this.idForLogging()}:`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1358,11 +1358,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
}
|
||||
|
||||
errors.forEach(e => {
|
||||
log.error(
|
||||
'Message.saveErrors:',
|
||||
e && e.reason ? e.reason : null,
|
||||
e && e.stack ? e.stack : e
|
||||
);
|
||||
log.error('Message.saveErrors:', Errors.toLogFormat(e));
|
||||
});
|
||||
errors = errors.map(e => {
|
||||
// Note: in our environment, instanceof can be scary, so we have a backup check
|
||||
|
@ -2415,7 +2411,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
sentAt: message.get('sent_at'),
|
||||
});
|
||||
} catch (error) {
|
||||
const errorText = error && error.stack ? error.stack : error;
|
||||
const errorText = Errors.toLogFormat(error);
|
||||
log.error(
|
||||
`${idLog}: Failed to process group update as part of message ${message.idForLogging()}: ${errorText}`
|
||||
);
|
||||
|
@ -3050,7 +3046,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
log.info(`${idLog}: Batching save`);
|
||||
this.saveAndNotify(conversation, confirm);
|
||||
} catch (error) {
|
||||
const errorForLog = error && error.stack ? error.stack : error;
|
||||
const errorForLog = Errors.toLogFormat(error);
|
||||
log.error(`${idLog}: error:`, errorForLog);
|
||||
throw error;
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ export async function routineProfileRefresh({
|
|||
} catch (err) {
|
||||
log.error(
|
||||
`${logId}: refreshed profile for ${conversation.idForLogging()}`,
|
||||
err?.stack || err
|
||||
Errors.toLogFormat(err)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import type {
|
|||
MaybeGrabLinkPreviewOptionsType,
|
||||
AddLinkPreviewOptionsType,
|
||||
} from '../types/LinkPreview';
|
||||
import * as Errors from '../types/errors';
|
||||
import type { StickerPackType as StickerPackDBType } from '../sql/Interface';
|
||||
import type { MIMEType } from '../types/MIME';
|
||||
import * as Bytes from '../Bytes';
|
||||
|
@ -216,7 +217,7 @@ export async function addLinkPreview(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'Problem loading link preview, disabling.',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
disableLinkPreviews = true;
|
||||
removeLinkPreview();
|
||||
|
@ -455,10 +456,7 @@ async function getStickerPackPreview(
|
|||
url,
|
||||
};
|
||||
} catch (error) {
|
||||
log.error(
|
||||
'getStickerPackPreview error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('getStickerPackPreview error:', Errors.toLogFormat(error));
|
||||
return null;
|
||||
} finally {
|
||||
if (id) {
|
||||
|
@ -530,7 +528,7 @@ async function getGroupPreview(
|
|||
),
|
||||
};
|
||||
} catch (error) {
|
||||
const errorString = error && error.stack ? error.stack : error;
|
||||
const errorString = Errors.toLogFormat(error);
|
||||
log.error(
|
||||
`getGroupPreview/${logId}: Failed to fetch avatar ${errorString}`
|
||||
);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import { requestMicrophonePermissions } from '../util/requestMicrophonePermissions';
|
||||
import * as log from '../logging/log';
|
||||
import type { WebAudioRecorderClass } from '../window.d';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
export class RecorderClass {
|
||||
private context?: AudioContext;
|
||||
|
@ -84,10 +85,7 @@ export class RecorderClass {
|
|||
this.source.connect(this.input);
|
||||
this.stream = stream;
|
||||
} catch (err) {
|
||||
log.error(
|
||||
'Recorder.onGetUserMediaError:',
|
||||
err && err.stack ? err.stack : err
|
||||
);
|
||||
log.error('Recorder.onGetUserMediaError:', Errors.toLogFormat(err));
|
||||
this.clear();
|
||||
throw err;
|
||||
}
|
||||
|
@ -135,7 +133,7 @@ export class RecorderClass {
|
|||
|
||||
this.clear();
|
||||
|
||||
log.error('Recorder/onError:', error && error.stack ? error.stack : error);
|
||||
log.error('Recorder/onError:', Errors.toLogFormat(error));
|
||||
}
|
||||
|
||||
getBlob(): Blob {
|
||||
|
|
|
@ -67,6 +67,7 @@ import {
|
|||
} from '../calling/findBestMatchingDevice';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import { UUID, UUIDKind } from '../types/UUID';
|
||||
import * as Errors from '../types/errors';
|
||||
import type { ConversationModel } from '../models/conversations';
|
||||
import * as Bytes from '../Bytes';
|
||||
import { uuidToBytes, bytesToUuid } from '../Crypto';
|
||||
|
@ -1061,10 +1062,7 @@ export class CallingClass {
|
|||
sendType: 'callingMessage',
|
||||
timestamp,
|
||||
}).catch(err => {
|
||||
log.error(
|
||||
'Failed to send group call update:',
|
||||
err && err.stack ? err.stack : err
|
||||
);
|
||||
log.error('Failed to send group call update:', Errors.toLogFormat(err));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1877,7 +1875,7 @@ export class CallingClass {
|
|||
|
||||
return await this.getCallSettings(conversation);
|
||||
} catch (err) {
|
||||
log.error(`Ignoring incoming call: ${err.stack}`);
|
||||
log.error(`Ignoring incoming call: ${Errors.toLogFormat(err)}`);
|
||||
this.addCallHistoryForFailedIncomingCall(
|
||||
conversation,
|
||||
call.isVideoCall,
|
||||
|
|
|
@ -7,6 +7,7 @@ import type { MessageModel } from '../models/messages';
|
|||
import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary';
|
||||
import { sleep } from '../util/sleep';
|
||||
import { SECOND } from '../util/durations';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
class ExpiringMessagesDeletionService {
|
||||
public update: typeof this.checkExpiringMessages;
|
||||
|
@ -65,7 +66,7 @@ class ExpiringMessagesDeletionService {
|
|||
} catch (error) {
|
||||
window.SignalContext.log.error(
|
||||
'destroyExpiredMessages: Error deleting expired messages',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
window.SignalContext.log.info(
|
||||
'destroyExpiredMessages: Waiting 30 seconds before trying again'
|
||||
|
|
|
@ -12,6 +12,7 @@ import { missingCaseError } from '../util/missingCaseError';
|
|||
import { waitForOnline } from '../util/waitForOnline';
|
||||
import * as log from '../logging/log';
|
||||
import type { StorageInterface } from '../types/Storage.d';
|
||||
import * as Errors from '../types/errors';
|
||||
import type { WebAPIType } from '../textsecure/WebAPI';
|
||||
import { SignalService as Proto } from '../protobuf';
|
||||
|
||||
|
@ -171,7 +172,7 @@ export class SenderCertificateService {
|
|||
`Sender certificate service could not fetch a ${modeToLogString(
|
||||
mode
|
||||
)} certificate. Returning undefined`,
|
||||
err && err.stack ? err.stack : err
|
||||
Errors.toLogFormat(err)
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import { debounce } from 'lodash';
|
||||
import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary';
|
||||
import { DAY } from '../util/durations';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
async function eraseTapToViewMessages() {
|
||||
try {
|
||||
|
@ -30,7 +31,7 @@ async function eraseTapToViewMessages() {
|
|||
} catch (error) {
|
||||
window.SignalContext.log.error(
|
||||
'eraseTapToViewMessages: Error erasing messages',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import * as log from '../logging/log';
|
||||
import { deleteAllLogs } from '../util/deleteAllLogs';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
export async function deleteAllData(): Promise<void> {
|
||||
try {
|
||||
|
@ -28,7 +29,7 @@ export async function deleteAllData(): Promise<void> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'Something went wrong deleting all data:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
window.restart();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import { parentPort } from 'worker_threads';
|
||||
|
||||
import type { LoggerType } from '../types/Logging';
|
||||
import * as Errors from '../types/errors';
|
||||
import type {
|
||||
WrappedWorkerRequest,
|
||||
WrappedWorkerResponse,
|
||||
|
@ -22,7 +23,7 @@ function respond(seq: number, error: Error | undefined, response?: any) {
|
|||
const wrappedResponse: WrappedWorkerResponse = {
|
||||
type: 'response',
|
||||
seq,
|
||||
error: error?.stack,
|
||||
error: error === undefined ? undefined : Errors.toLogFormat(error),
|
||||
response,
|
||||
};
|
||||
port.postMessage(wrappedResponse);
|
||||
|
|
|
@ -55,6 +55,7 @@ import { CallMode } from '../../types/Calling';
|
|||
import type { MediaItemType } from '../../types/MediaItem';
|
||||
import type { UUIDStringType } from '../../types/UUID';
|
||||
import { MY_STORY_ID, StorySendMode } from '../../types/Stories';
|
||||
import * as Errors from '../../types/errors';
|
||||
import {
|
||||
getGroupSizeRecommendedLimit,
|
||||
getGroupSizeHardLimit,
|
||||
|
@ -1206,7 +1207,7 @@ function myProfileChanged(
|
|||
payload: null,
|
||||
});
|
||||
} catch (err) {
|
||||
log.error('myProfileChanged', err && err.stack ? err.stack : err);
|
||||
log.error('myProfileChanged', Errors.toLogFormat(err));
|
||||
dispatch({ type: TOGGLE_PROFILE_EDITOR_ERROR });
|
||||
}
|
||||
};
|
||||
|
@ -1606,7 +1607,7 @@ function createGroup(
|
|||
})
|
||||
);
|
||||
} catch (err) {
|
||||
log.error('Failed to create group', err && err.stack ? err.stack : err);
|
||||
log.error('Failed to create group', Errors.toLogFormat(err));
|
||||
dispatch({ type: 'CREATE_GROUP_REJECTED' });
|
||||
}
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
toggleVerification,
|
||||
} from '../../shims/contactVerification';
|
||||
import * as log from '../../logging/log';
|
||||
import * as Errors from '../../types/errors';
|
||||
|
||||
export type SafetyNumberContactType = {
|
||||
safetyNumber: string;
|
||||
|
@ -108,10 +109,7 @@ async function alterVerification(contact: ConversationType): Promise<void> {
|
|||
if (result.name === 'OutgoingIdentityKeyError') {
|
||||
throw result;
|
||||
} else {
|
||||
log.error(
|
||||
'failed to toggle verified:',
|
||||
result && result.stack ? result.stack : result
|
||||
);
|
||||
log.error('failed to toggle verified:', Errors.toLogFormat(result));
|
||||
}
|
||||
} else {
|
||||
const keyError = result.errors.find(
|
||||
|
@ -121,10 +119,7 @@ async function alterVerification(contact: ConversationType): Promise<void> {
|
|||
throw keyError;
|
||||
} else {
|
||||
result.errors.forEach((error: Error) => {
|
||||
log.error(
|
||||
'failed to toggle verified:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('failed to toggle verified:', Errors.toLogFormat(error));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import type { StateType } from '../reducer';
|
|||
import * as log from '../../logging/log';
|
||||
import { ForwardMessageModal } from '../../components/ForwardMessageModal';
|
||||
import { LinkPreviewSourceType } from '../../types/LinkPreview';
|
||||
import * as Errors from '../../types/errors';
|
||||
import type { GetConversationByIdType } from '../selectors/conversations';
|
||||
import {
|
||||
getAllComposableConversations,
|
||||
|
@ -107,7 +108,7 @@ export function SmartForwardMessageModal(): JSX.Element | null {
|
|||
closeModal();
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn('doForwardMessage', err && err.stack ? err.stack : err);
|
||||
log.warn('doForwardMessage', Errors.toLogFormat(err));
|
||||
}
|
||||
}}
|
||||
getPreferredBadge={getPreferredBadge}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import { assert } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import { LibSignalErrorBase } from '@signalapp/libsignal-client';
|
||||
|
||||
import {
|
||||
_analyzeSenderKeyDevices,
|
||||
|
@ -172,7 +173,11 @@ describe('sendToGroup', () => {
|
|||
});
|
||||
|
||||
it("returns true for any error with 'untrusted' identity", async () => {
|
||||
const error = new Error('This was an untrusted identity.');
|
||||
const error = new LibSignalErrorBase(
|
||||
'untrusted identity',
|
||||
'UntrustedIdentity',
|
||||
'ignored'
|
||||
);
|
||||
assert.isTrue(_shouldFailSend(error, 'logId'));
|
||||
});
|
||||
|
||||
|
|
|
@ -575,7 +575,7 @@ export default class AccountManager extends EventTarget {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'Something went wrong deleting data from previous number',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -8,6 +8,7 @@ import protobuf from '../protobuf/wrap';
|
|||
import { SignalService as Proto } from '../protobuf';
|
||||
import { normalizeUuid } from '../util/normalizeUuid';
|
||||
import { DurationInSeconds } from '../util/durations';
|
||||
import * as Errors from '../types/errors';
|
||||
import * as log from '../logging/log';
|
||||
|
||||
import Avatar = Proto.ContactDetails.IAvatar;
|
||||
|
@ -90,10 +91,7 @@ abstract class ParserBase<
|
|||
expireTimer,
|
||||
};
|
||||
} catch (error) {
|
||||
log.error(
|
||||
'ProtoParser.next error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('ProtoParser.next error:', Errors.toLogFormat(error));
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,8 +54,9 @@ export class ReplayableError extends Error {
|
|||
name?: string;
|
||||
message: string;
|
||||
functionCode?: number;
|
||||
cause?: unknown;
|
||||
}) {
|
||||
super(options.message);
|
||||
super(options.message, { cause: options.cause });
|
||||
|
||||
this.name = options.name || 'ReplayableError';
|
||||
this.message = options.message;
|
||||
|
@ -71,7 +72,7 @@ export class ReplayableError extends Error {
|
|||
}
|
||||
|
||||
export class OutgoingIdentityKeyError extends ReplayableError {
|
||||
identifier: string;
|
||||
public readonly identifier: string;
|
||||
|
||||
// Note: Data to resend message is no longer captured
|
||||
constructor(incomingIdentifier: string) {
|
||||
|
@ -162,6 +163,7 @@ export class SendMessageChallengeError extends ReplayableError {
|
|||
super({
|
||||
name: 'SendMessageChallengeError',
|
||||
message: httpError.message,
|
||||
cause: httpError,
|
||||
});
|
||||
|
||||
[this.identifier] = identifier.split('.');
|
||||
|
@ -237,9 +239,7 @@ export class SendMessageProtoError extends Error implements CallbackResultType {
|
|||
return 'No errors';
|
||||
}
|
||||
|
||||
return errors
|
||||
.map(error => (error.stackForLog ? error.stackForLog : error.toString()))
|
||||
.join(', ');
|
||||
return errors.map(error => error.toString()).join(', ');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ import type {
|
|||
PlaintextContent,
|
||||
} from '@signalapp/libsignal-client';
|
||||
import {
|
||||
ErrorCode,
|
||||
LibSignalErrorBase,
|
||||
CiphertextMessageType,
|
||||
ProtocolAddress,
|
||||
sealedSenderEncrypt,
|
||||
|
@ -34,6 +36,7 @@ import {
|
|||
import type { CallbackResultType, CustomError } from './Types.d';
|
||||
import { isValidNumber } from '../types/PhoneNumber';
|
||||
import { Address } from '../types/Address';
|
||||
import * as Errors from '../types/errors';
|
||||
import { QualifiedAddress } from '../types/QualifiedAddress';
|
||||
import { UUID, isValidUuid } from '../types/UUID';
|
||||
import { Sessions, IdentityKeys } from '../LibSignalStores';
|
||||
|
@ -244,8 +247,7 @@ export default class OutgoingMessage {
|
|||
}
|
||||
}
|
||||
|
||||
error.reason = reason;
|
||||
error.stackForLog = providedError ? providedError.stack : undefined;
|
||||
error.cause = reason;
|
||||
|
||||
this.errors[this.errors.length] = error;
|
||||
this.numberCompleted();
|
||||
|
@ -284,7 +286,6 @@ export default class OutgoingMessage {
|
|||
: { accessKey: undefined };
|
||||
const { accessKey } = info;
|
||||
|
||||
try {
|
||||
const { accessKeyFailed } = await getKeysForIdentifier(
|
||||
identifier,
|
||||
this.server,
|
||||
|
@ -294,12 +295,6 @@ export default class OutgoingMessage {
|
|||
if (accessKeyFailed && !this.failoverIdentifiers.includes(identifier)) {
|
||||
this.failoverIdentifiers.push(identifier);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error?.message?.includes('untrusted identity for address')) {
|
||||
error.timestamp = this.timestamp;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async transmitMessage(
|
||||
|
@ -626,8 +621,13 @@ export default class OutgoingMessage {
|
|||
);
|
||||
});
|
||||
}
|
||||
if (error?.message?.includes('untrusted identity for address')) {
|
||||
error.timestamp = this.timestamp;
|
||||
|
||||
let newError = error;
|
||||
if (
|
||||
error instanceof LibSignalErrorBase &&
|
||||
error.code === ErrorCode.UntrustedIdentity
|
||||
) {
|
||||
newError = new OutgoingIdentityKeyError(identifier);
|
||||
log.error(
|
||||
'Got "key changed" error from encrypt - no identityKey for application layer',
|
||||
identifier,
|
||||
|
@ -643,7 +643,8 @@ export default class OutgoingMessage {
|
|||
},
|
||||
innerError => {
|
||||
log.error(
|
||||
`doSendMessage: Error closing sessions: ${innerError.stack}`
|
||||
'doSendMessage: Error closing sessions: ' +
|
||||
`${Errors.toLogFormat(innerError)}`
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
@ -653,7 +654,7 @@ export default class OutgoingMessage {
|
|||
this.registerError(
|
||||
identifier,
|
||||
'Failed to create or send message',
|
||||
error
|
||||
newError
|
||||
);
|
||||
|
||||
return undefined;
|
||||
|
@ -712,7 +713,7 @@ export default class OutgoingMessage {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`sendToIdentifier: Failed to fetch UUID for identifier ${identifier}`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -731,7 +732,10 @@ export default class OutgoingMessage {
|
|||
}
|
||||
await this.reloadDevicesAndSend(identifier, true)();
|
||||
} catch (error) {
|
||||
if (error?.message?.includes('untrusted identity for address')) {
|
||||
if (
|
||||
error instanceof LibSignalErrorBase &&
|
||||
error.code === ErrorCode.UntrustedIdentity
|
||||
) {
|
||||
const newError = new OutgoingIdentityKeyError(identifier);
|
||||
this.registerError(identifier, 'Untrusted identity', newError);
|
||||
} else {
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import {
|
||||
ErrorCode,
|
||||
LibSignalErrorBase,
|
||||
PreKeyBundle,
|
||||
processPreKeyBundle,
|
||||
ProtocolAddress,
|
||||
|
@ -9,9 +11,9 @@ import {
|
|||
} from '@signalapp/libsignal-client';
|
||||
|
||||
import {
|
||||
OutgoingIdentityKeyError,
|
||||
UnregisteredUserError,
|
||||
HTTPError,
|
||||
OutgoingIdentityKeyError,
|
||||
} from './Errors';
|
||||
import { Sessions, IdentityKeys } from '../LibSignalStores';
|
||||
import { Address } from '../types/Address';
|
||||
|
@ -72,13 +74,6 @@ async function getServerKeys(
|
|||
}),
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
if (
|
||||
error instanceof Error &&
|
||||
error.message.includes('untrusted identity')
|
||||
) {
|
||||
throw new OutgoingIdentityKeyError(identifier);
|
||||
}
|
||||
|
||||
if (
|
||||
accessKey &&
|
||||
isRecord(error) &&
|
||||
|
@ -155,22 +150,27 @@ async function handleServerKeys(
|
|||
ourUuid,
|
||||
new Address(theirUuid, deviceId)
|
||||
);
|
||||
await window.textsecure.storage.protocol
|
||||
.enqueueSessionJob(address, () =>
|
||||
|
||||
try {
|
||||
await window.textsecure.storage.protocol.enqueueSessionJob(
|
||||
address,
|
||||
() =>
|
||||
processPreKeyBundle(
|
||||
preKeyBundle,
|
||||
protocolAddress,
|
||||
sessionStore,
|
||||
identityKeyStore
|
||||
)
|
||||
)
|
||||
.catch(error => {
|
||||
if (error?.message?.includes('untrusted identity for address')) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
error.identityKey = response.identityKey;
|
||||
);
|
||||
} catch (error) {
|
||||
if (
|
||||
error instanceof LibSignalErrorBase &&
|
||||
error.code === ErrorCode.UntrustedIdentity
|
||||
) {
|
||||
throw new OutgoingIdentityKeyError(identifier);
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -529,7 +529,7 @@ export async function downloadEphemeralPack(
|
|||
}
|
||||
log.error(
|
||||
`Ephemeral download error for sticker pack ${redactPackId(packId)}:`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -554,7 +554,7 @@ export async function downloadStickerPack(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'doDownloadStickerPack threw an error:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -696,7 +696,7 @@ async function doDownloadStickerPack(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`Error downloading manifest for sticker pack ${redactPackId(packId)}:`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
|
||||
const pack = {
|
||||
|
@ -779,7 +779,7 @@ async function doDownloadStickerPack(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`Error downloading stickers for sticker pack ${redactPackId(packId)}:`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
|
||||
const errorStatus = 'error';
|
||||
|
|
|
@ -4,15 +4,20 @@
|
|||
import { get, has } from 'lodash';
|
||||
|
||||
export function toLogFormat(error: unknown): string {
|
||||
let result = '';
|
||||
if (error instanceof Error && error.stack) {
|
||||
return error.stack;
|
||||
result = error.stack;
|
||||
} else if (has(error, 'message')) {
|
||||
result = get(error, 'message');
|
||||
} else {
|
||||
result = String(error);
|
||||
}
|
||||
|
||||
if (has(error, 'message')) {
|
||||
return get(error, 'message');
|
||||
if (has(error, 'cause')) {
|
||||
result += `\nCaused by: ${String(get(error, 'cause'))}`;
|
||||
}
|
||||
|
||||
return String(error);
|
||||
return result;
|
||||
}
|
||||
|
||||
export class ProfileDecryptError extends Error {}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import { getEnvironment, Environment } from '../environment';
|
||||
import * as log from '../logging/log';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
/**
|
||||
* In production and beta, logs a warning and continues. For development it
|
||||
|
@ -15,7 +16,7 @@ export function softAssert(condition: unknown, message: string): void {
|
|||
}
|
||||
|
||||
const err = new Error(message);
|
||||
log.warn('softAssert failure:', err && err.stack ? err.stack : err);
|
||||
log.warn('softAssert failure:', Errors.toLogFormat(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +35,7 @@ export function assertDev(
|
|||
}
|
||||
throw err;
|
||||
}
|
||||
log.error('assert failure:', err && err.stack ? err.stack : err);
|
||||
log.error('assert failure:', Errors.toLogFormat(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ import { getValue } from '../RemoteConfig';
|
|||
|
||||
import { parseIntOrThrow } from './parseIntOrThrow';
|
||||
import { scaleImageToLevel } from './scaleImageToLevel';
|
||||
import { isRecord } from './isRecord';
|
||||
import type { AttachmentType } from '../types/Attachment';
|
||||
import { canBeTranscoded } from '../types/Attachment';
|
||||
import type { LoggerType } from '../types/Logging';
|
||||
import * as MIME from '../types/MIME';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
const MEBIBYTE = 1024 * 1024;
|
||||
const DEFAULT_MAX = 100 * MEBIBYTE;
|
||||
|
@ -87,8 +87,7 @@ export async function autoOrientJPEG(
|
|||
|
||||
return xcodedAttachment;
|
||||
} catch (error: unknown) {
|
||||
const errorString =
|
||||
isRecord(error) && 'stack' in error ? error.stack : error;
|
||||
const errorString = Errors.toLogFormat(error);
|
||||
logger.error(
|
||||
'autoOrientJPEG: Failed to rotate/scale attachment',
|
||||
errorString
|
||||
|
|
|
@ -14,6 +14,7 @@ import type {
|
|||
DefaultConversationColorType,
|
||||
} from '../types/Colors';
|
||||
import { DEFAULT_CONVERSATION_COLOR } from '../types/Colors';
|
||||
import * as Errors from '../types/errors';
|
||||
import * as Stickers from '../types/Stickers';
|
||||
import type { SystemTraySetting } from '../types/SystemTraySetting';
|
||||
import { parseSystemTraySetting } from '../types/SystemTraySetting';
|
||||
|
@ -453,7 +454,7 @@ export function createIPCEvents(
|
|||
window.isShowingModal = false;
|
||||
log.error(
|
||||
'showStickerPack: Ran into an error!',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
const errorView = new ReactWrapperView({
|
||||
className: 'error-modal-wrapper',
|
||||
|
@ -483,7 +484,7 @@ export function createIPCEvents(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'showGroupViaLink: Ran into an error!',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
const errorView = new ReactWrapperView({
|
||||
className: 'error-modal-wrapper',
|
||||
|
|
|
@ -102,7 +102,7 @@ export async function onRetryRequest(event: RetryRequestEvent): Promise<void> {
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`onRetryRequest/${logId}: Failed to parse integer from desktop.retryRespondMaxAge feature flag`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -349,7 +349,7 @@ async function sendDistributionMessageOrNullMessage(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`sendDistributionMessageOrNullMessage/${logId}: Failed to send sender key distribution message`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -651,7 +651,7 @@ async function requestResend(decryptionError: DecryptionErrorEventData) {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`requestResend/${logId}: Failed to send retry request, failing over to automatic reset`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
startAutomaticSessionReset(decryptionError);
|
||||
return;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import { Environment, getEnvironment } from '../environment';
|
||||
import { isInPast } from './timestamp';
|
||||
import * as log from '../logging/log';
|
||||
import * as Errors from '../types/errors';
|
||||
|
||||
const ONE_DAY_MS = 86400 * 1000;
|
||||
const NINETY_ONE_DAYS = 91 * ONE_DAY_MS;
|
||||
|
@ -18,7 +19,7 @@ export function hasExpired(): boolean {
|
|||
log.info('Build expires: ', new Date(buildExpiration).toISOString());
|
||||
}
|
||||
} catch (e) {
|
||||
log.error('Error retrieving build expiration date', e.stack);
|
||||
log.error('Error retrieving build expiration date', Errors.toLogFormat(e));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ const loadImageData = async (input: Input): Promise<ImageData> => {
|
|||
canvasOrError => {
|
||||
if (canvasOrError instanceof Event && canvasOrError.type === 'error') {
|
||||
const processError = new Error(
|
||||
'imageToBlurHash: Failed to process image'
|
||||
'imageToBlurHash: Failed to process image',
|
||||
{ cause: canvasOrError }
|
||||
);
|
||||
processError.originalError = canvasOrError;
|
||||
reject(processError);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import { ReactWrapperView } from '../views/ReactWrapperView';
|
|||
import { ErrorModal } from '../components/ErrorModal';
|
||||
import { ProgressModal } from '../components/ProgressModal';
|
||||
import * as log from '../logging/log';
|
||||
import * as Errors from '../types/errors';
|
||||
import { clearTimeoutIfNecessary } from './clearTimeoutIfNecessary';
|
||||
|
||||
export async function longRunningTaskWrapper<T>({
|
||||
|
@ -62,7 +63,7 @@ export async function longRunningTaskWrapper<T>({
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`longRunningTaskWrapper/${idLog}: Error!`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
|
||||
clearTimeoutIfNecessary(progressTimeout);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import { ipcRenderer } from 'electron';
|
||||
|
||||
import { strictAssert } from './assert';
|
||||
import * as Errors from '../types/errors';
|
||||
import type { UnwrapPromise } from '../types/Util';
|
||||
import type {
|
||||
IPCEventsValuesType,
|
||||
|
@ -104,11 +105,7 @@ export function installSetting(
|
|||
try {
|
||||
ipcRenderer.send('settings:response', seq, null, await getFn());
|
||||
} catch (error) {
|
||||
ipcRenderer.send(
|
||||
'settings:response',
|
||||
seq,
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
ipcRenderer.send('settings:response', seq, Errors.toLogFormat(error));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -132,11 +129,7 @@ export function installSetting(
|
|||
await setFn(value);
|
||||
ipcRenderer.send('settings:response', seq, null);
|
||||
} catch (error) {
|
||||
ipcRenderer.send(
|
||||
'settings:response',
|
||||
seq,
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
ipcRenderer.send('settings:response', seq, Errors.toLogFormat(error));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -152,11 +145,7 @@ export function installCallback<Name extends keyof IPCEventsCallbacksType>(
|
|||
try {
|
||||
ipcRenderer.send('settings:response', seq, null, await hook(...args));
|
||||
} catch (error) {
|
||||
ipcRenderer.send(
|
||||
'settings:response',
|
||||
seq,
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
ipcRenderer.send('settings:response', seq, Errors.toLogFormat(error));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import type {
|
|||
AttachmentDraftType,
|
||||
InMemoryAttachmentDraftType,
|
||||
} from '../types/Attachment';
|
||||
import * as Errors from '../types/errors';
|
||||
import { getMaximumAttachmentSize } from './attachments';
|
||||
import { AttachmentToastType } from '../types/AttachmentToastType';
|
||||
import { fileToBytes } from './fileToBytes';
|
||||
|
@ -105,7 +106,7 @@ export async function processAttachment(
|
|||
} catch (e) {
|
||||
log.error(
|
||||
`Was unable to generate thumbnail for fileType ${fileType}`,
|
||||
e && e.stack ? e.stack : e
|
||||
Errors.toLogFormat(e)
|
||||
);
|
||||
const data = await fileToBytes(file);
|
||||
attachment = {
|
||||
|
@ -125,7 +126,7 @@ export async function processAttachment(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'Error ensuring that image is properly sized:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
|
||||
throw error;
|
||||
|
|
|
@ -19,6 +19,7 @@ import type {
|
|||
MessageAttributesType,
|
||||
QuotedMessageType,
|
||||
} from '../model-types.d';
|
||||
import * as Errors from '../types/errors';
|
||||
import type { StickerType } from '../types/Stickers';
|
||||
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
||||
|
||||
|
@ -222,7 +223,7 @@ export async function queueAttachmentDownloads(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`Problem copying sticker (${packId}, ${stickerId}) to attachments:`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import { IMAGE_JPEG } from '../types/MIME';
|
|||
import { canvasToBlob } from './canvasToBlob';
|
||||
import { getValue } from '../RemoteConfig';
|
||||
import { parseNumber } from './libphonenumberUtil';
|
||||
import { isRecord } from './isRecord';
|
||||
|
||||
enum MediaQualityLevels {
|
||||
One = 1,
|
||||
|
@ -126,13 +125,10 @@ export async function scaleImageToLevel(
|
|||
throw new Error('image not a canvas');
|
||||
}
|
||||
({ image } = data);
|
||||
} catch (err) {
|
||||
const errorString = isRecord(err) && 'stack' in err ? err.stack : err;
|
||||
const error = new Error(
|
||||
'scaleImageToLevel: Failed to process image',
|
||||
errorString
|
||||
);
|
||||
error.originalError = err;
|
||||
} catch (cause) {
|
||||
const error = new Error('scaleImageToLevel: Failed to process image', {
|
||||
cause,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import { differenceWith, omit, partition } from 'lodash';
|
|||
|
||||
import {
|
||||
ErrorCode,
|
||||
LibSignalErrorBase,
|
||||
groupEncrypt,
|
||||
ProtocolAddress,
|
||||
sealedSenderMultiRecipientEncrypt,
|
||||
|
@ -21,6 +22,7 @@ import {
|
|||
import { Address } from '../types/Address';
|
||||
import { QualifiedAddress } from '../types/QualifiedAddress';
|
||||
import { UUID } from '../types/UUID';
|
||||
import * as Errors from '../types/errors';
|
||||
import { getValue, isEnabled } from '../RemoteConfig';
|
||||
import type { UUIDStringType } from '../types/UUID';
|
||||
import { isRecord } from './isRecord';
|
||||
|
@ -216,7 +218,7 @@ export async function sendContentMessageToGroup({
|
|||
|
||||
log.error(
|
||||
`sendToGroup/${logId}: Sender Key send failed, logging, proceeding to normal send`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -581,7 +583,10 @@ export async function sendToGroupViaSenderKey(options: {
|
|||
recursionCount: recursionCount + 1,
|
||||
});
|
||||
}
|
||||
if (error.code === ErrorCode.InvalidRegistrationId && error.addr) {
|
||||
if (
|
||||
error instanceof LibSignalErrorBase &&
|
||||
error.code === ErrorCode.InvalidRegistrationId
|
||||
) {
|
||||
const address = error.addr as ProtocolAddress;
|
||||
const name = address.name();
|
||||
|
||||
|
@ -742,7 +747,7 @@ function getSenderKeyExpireDuration(): number {
|
|||
} catch (error) {
|
||||
log.warn(
|
||||
`getSenderKeyExpireDuration: Failed to parse integer. Using default of ${MAX_SENDER_KEY_EXPIRE_DURATION}.`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return MAX_SENDER_KEY_EXPIRE_DURATION;
|
||||
}
|
||||
|
@ -753,7 +758,10 @@ export function _shouldFailSend(error: unknown, logId: string): boolean {
|
|||
log.error(`_shouldFailSend/${logId}: ${message}`);
|
||||
};
|
||||
|
||||
if (error instanceof Error && error.message.includes('untrusted identity')) {
|
||||
if (
|
||||
error instanceof LibSignalErrorBase &&
|
||||
error.code === ErrorCode.UntrustedIdentity
|
||||
) {
|
||||
logError("'untrusted identity' error, failing.");
|
||||
return true;
|
||||
}
|
||||
|
@ -1271,7 +1279,7 @@ async function fetchKeysForIdentifiers(
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'fetchKeysForIdentifiers: Failed to fetch keys:',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import { render } from 'mustache';
|
|||
import type { AttachmentType } from '../types/Attachment';
|
||||
import { isGIF } from '../types/Attachment';
|
||||
import * as Stickers from '../types/Stickers';
|
||||
import * as Errors from '../types/errors';
|
||||
import type { DraftBodyRangesType } from '../types/Util';
|
||||
import type { MIMEType } from '../types/MIME';
|
||||
import type { ConversationModel } from '../models/conversations';
|
||||
|
@ -1693,7 +1694,7 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'Error sending delete-for-everyone',
|
||||
error && error.stack,
|
||||
Errors.toLogFormat(error),
|
||||
messageId
|
||||
);
|
||||
showToast(ToastDeleteForEveryoneFailed);
|
||||
|
@ -2375,7 +2376,7 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
|
|||
const { packId, stickerId } = options;
|
||||
this.model.sendStickerMessage(packId, stickerId);
|
||||
} catch (error) {
|
||||
log.error('clickSend error:', error && error.stack ? error.stack : error);
|
||||
log.error('clickSend error:', Errors.toLogFormat(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2531,10 +2532,7 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
|
|||
}
|
||||
} catch (error) {
|
||||
this.enableMessageField();
|
||||
log.error(
|
||||
'sendMessage error:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
log.error('sendMessage error:', Errors.toLogFormat(error));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2596,7 +2594,7 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
'Error pulling attached files before send',
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
} finally {
|
||||
this.enableMessageField();
|
||||
|
|
25
ts/window.d.ts
vendored
25
ts/window.d.ts
vendored
|
@ -3,13 +3,10 @@
|
|||
|
||||
// Captures the globals put in place by preload.js, background.js and others
|
||||
|
||||
/* eslint-disable max-classes-per-file */
|
||||
|
||||
import type { Store } from 'redux';
|
||||
import type * as Backbone from 'backbone';
|
||||
import type * as Underscore from 'underscore';
|
||||
import type PQueue from 'p-queue/dist';
|
||||
import type { Ref } from 'react';
|
||||
import type { assert } from 'chai';
|
||||
import type * as Mustache from 'mustache';
|
||||
|
||||
|
@ -358,15 +355,6 @@ declare global {
|
|||
};
|
||||
}
|
||||
|
||||
interface Error {
|
||||
originalError?: Event;
|
||||
reason?: unknown;
|
||||
stackForLog?: string;
|
||||
|
||||
// Used in sticker creator to attach messages to errors
|
||||
errorMessageI18nKey?: string;
|
||||
}
|
||||
|
||||
interface Element {
|
||||
// WebKit-specific
|
||||
scrollIntoViewIfNeeded: (bringToCenter?: boolean) => void;
|
||||
|
@ -387,19 +375,6 @@ declare global {
|
|||
}
|
||||
}
|
||||
|
||||
export class GumVideoCapturer {
|
||||
constructor(
|
||||
maxWidth: number,
|
||||
maxHeight: number,
|
||||
maxFramerate: number,
|
||||
localPreview: Ref<HTMLVideoElement>
|
||||
);
|
||||
}
|
||||
|
||||
export class CanvasVideoRenderer {
|
||||
constructor(canvas: Ref<HTMLCanvasElement>);
|
||||
}
|
||||
|
||||
export type WhisperType = {
|
||||
Conversation: typeof ConversationModel;
|
||||
ConversationCollection: typeof ConversationModelCollectionType;
|
||||
|
|
|
@ -11,6 +11,7 @@ import { ThemeType } from '../../types/Util';
|
|||
import { getEnvironment, Environment } from '../../environment';
|
||||
import { SignalContext } from '../context';
|
||||
import * as log from '../../logging/log';
|
||||
import * as Errors from '../../types/errors';
|
||||
|
||||
import { strictAssert } from '../../util/assert';
|
||||
|
||||
|
@ -90,7 +91,7 @@ window.isBeforeVersion = (toCheck, baseVersion) => {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`isBeforeVersion error: toCheck: ${toCheck}, baseVersion: ${baseVersion}`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
@ -101,7 +102,7 @@ window.isAfterVersion = (toCheck, baseVersion) => {
|
|||
} catch (error) {
|
||||
log.error(
|
||||
`isBeforeVersion error: toCheck: ${toCheck}, baseVersion: ${baseVersion}`,
|
||||
error && error.stack ? error.stack : error
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
@ -305,7 +306,7 @@ ipc.on('delete-all-data', async () => {
|
|||
try {
|
||||
await deleteAllData();
|
||||
} catch (error) {
|
||||
log.error('delete-all-data: error', error && error.stack);
|
||||
log.error('delete-all-data: error', Errors.toLogFormat(error));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -362,10 +363,7 @@ ipc.on('get-ready-for-shutdown', async () => {
|
|||
await shutdown();
|
||||
ipc.send('now-ready-for-shutdown');
|
||||
} catch (error) {
|
||||
ipc.send(
|
||||
'now-ready-for-shutdown',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
ipc.send('now-ready-for-shutdown', Errors.toLogFormat(error));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ const port = parentPort;
|
|||
function respond(uuid: string, error: Error | undefined, response?: File) {
|
||||
const wrappedResponse: WrappedWorkerResponse = {
|
||||
uuid,
|
||||
error: error ? error.stack : undefined,
|
||||
error: error?.stack,
|
||||
response,
|
||||
};
|
||||
port.postMessage(wrappedResponse);
|
||||
|
|
Loading…
Reference in a new issue