Skip to content

Commit

Permalink
feat: using cause property to establish error chain
Browse files Browse the repository at this point in the history
When any error is thrown as the result of another error occurring, the original error is now contained within the `cause` property of the new error.

#304
emmacasolin committed Jun 7, 2022

Verified

This commit was signed with the committer’s verified signature.
apoelstra Andrew Poelstra
1 parent 4977305 commit b14b240
Showing 24 changed files with 77 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/bin/keys/CommandDecrypt.ts
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ class CommandDecrypt extends CommandPolykey {
code: e.code,
path: e.path,
},
cause: e,
});
}
cryptoMessage.setData(cipherText);
1 change: 1 addition & 0 deletions src/bin/keys/CommandEncrypt.ts
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ class CommandEncypt extends CommandPolykey {
code: e.code,
path: e.path,
},
cause: e,
});
}
cryptoMessage.setData(plainText);
1 change: 1 addition & 0 deletions src/bin/keys/CommandSign.ts
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ class CommandSign extends CommandPolykey {
code: e.code,
path: e.path,
},
cause: e,
});
}
cryptoMessage.setData(data);
1 change: 1 addition & 0 deletions src/bin/keys/CommandVerify.ts
Original file line number Diff line number Diff line change
@@ -66,6 +66,7 @@ class CommandVerify extends CommandPolykey {
code: e.code,
path: e.path,
},
cause: e,
});
}
cryptoMessage.setData(data);
2 changes: 1 addition & 1 deletion src/bin/nodes/CommandPing.ts
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ class CommandPing extends CommandPolykey {
error = new binErrors.ErrorNodePingFailed(
`Failed to resolve node ID ${nodesUtils.encodeNodeId(
nodeId,
)} to an address.`,
)} to an address.`, { cause: err },
);
} else {
throw err;
1 change: 1 addition & 0 deletions src/bin/secrets/CommandCreate.ts
Original file line number Diff line number Diff line change
@@ -71,6 +71,7 @@ class CommandCreate extends CommandPolykey {
code: e.code,
path: e.path,
},
cause: e,
});
}
secretMessage.setSecretContent(content);
1 change: 1 addition & 0 deletions src/bin/secrets/CommandEdit.ts
Original file line number Diff line number Diff line change
@@ -80,6 +80,7 @@ class CommandEdit extends CommandPolykey {
code: e.code,
path: e.path,
},
cause: e,
});
}
secretMessage.setVault(vaultMessage);
1 change: 1 addition & 0 deletions src/bin/secrets/CommandUpdate.ts
Original file line number Diff line number Diff line change
@@ -71,6 +71,7 @@ class CommandUpdate extends CommandPolykey {
code: e.code,
path: e.path,
},
cause: e,
});
}
secretMessage.setSecretContent(content);
4 changes: 4 additions & 0 deletions src/bin/utils/processors.ts
Original file line number Diff line number Diff line change
@@ -95,6 +95,7 @@ async function processPassword(
code: e.code,
path: e.path,
},
cause: e,
});
}
} else if (typeof process.env['PK_PASSWORD'] === 'string') {
@@ -139,6 +140,7 @@ async function processNewPassword(
code: e.code,
path: e.path,
},
cause: e,
});
}
} else if (!existing && typeof process.env['PK_PASSWORD'] === 'string') {
@@ -177,6 +179,7 @@ async function processRecoveryCode(
code: e.code,
path: e.path,
},
cause: e,
});
}
} else if (typeof process.env['PK_RECOVERY_CODE'] === 'string') {
@@ -384,6 +387,7 @@ async function processAuthentication(
code: e.code,
path: e.path,
},
cause: e,
});
}
meta = clientUtils.encodeAuthFromPassword(password);
8 changes: 5 additions & 3 deletions src/grpc/GRPCClient.ts
Original file line number Diff line number Diff line change
@@ -129,7 +129,7 @@ abstract class GRPCClient<T extends Client = Client> {
} catch (e) {
// If we fail here then we leak the client object...
client.close();
throw new grpcErrors.ErrorGRPCClientTimeout();
throw new grpcErrors.ErrorGRPCClientTimeout(e.message, { cause: e });
}
let serverCertChain: Array<Certificate> | undefined;
if (channelCredentials._isSecure()) {
@@ -151,8 +151,10 @@ abstract class GRPCClient<T extends Client = Client> {
`Failed GRPC server certificate verification connecting to ${address}`,
);
const e_ = new grpcErrors.ErrorGRPCClientVerification(
`${e.name}: ${e.message}`,
e.data,
`${e.name}: ${e.message}`,{
data: e.data,
cause: e,
},
);
session.destroy(e_, http2.constants.NGHTTP2_PROTOCOL_ERROR);
}
10 changes: 6 additions & 4 deletions src/grpc/GRPCServer.ts
Original file line number Diff line number Diff line change
@@ -70,7 +70,7 @@ class GRPCServer {
try {
this.port = await bindAsync(address, serverCredentials);
} catch (e) {
throw new grpcErrors.ErrorGRPCServerBind(e.message);
throw new grpcErrors.ErrorGRPCServerBind(e.message, { cause: e });
}
if (serverCredentials._isSecure()) {
// @ts-ignore hack for private property
@@ -100,8 +100,10 @@ class GRPCServer {
`Failed GRPC client certificate verification connecting from ${address}`,
);
const e_ = new grpcErrors.ErrorGRPCServerVerification(
`${e.name}: ${e.message}`,
e.data,
`${e.name}: ${e.message}`, {
data: e.data,
cause: e,
},
);
session.destroy(e_, http2.constants.NGHTTP2_PROTOCOL_ERROR);
} else {
@@ -140,7 +142,7 @@ class GRPCServer {
...(timer != null ? [timer.timerP] : []),
]);
} catch (e) {
throw new grpcErrors.ErrorGRPCServerShutdown(e.message);
throw new grpcErrors.ErrorGRPCServerShutdown(e.message, { cause: e });
} finally {
if (timer != null) timerStop(timer);
}
8 changes: 7 additions & 1 deletion src/identities/providers/github/GitHubProvider.ts
Original file line number Diff line number Diff line change
@@ -120,7 +120,7 @@ class GitHubProvider extends Provider {
data = await response.json();
} catch (e) {
throw new identitiesErrors.ErrorProviderAuthentication(
'Provider access token response is not valid JSON',
'Provider access token response is not valid JSON', { cause: e },
);
}
if (data.error) {
@@ -200,6 +200,7 @@ class GitHubProvider extends Provider {
} catch (e) {
throw new identitiesErrors.ErrorProviderCall(
`Provider response body is not valid JSON`,
{ cause: e },
);
}
return data.login;
@@ -246,6 +247,7 @@ class GitHubProvider extends Provider {
} catch (e) {
throw new identitiesErrors.ErrorProviderCall(
`Provider response body is not valid JSON`,
{ cause: e },
);
}
return {
@@ -297,6 +299,7 @@ class GitHubProvider extends Provider {
} catch (e) {
throw new identitiesErrors.ErrorProviderCall(
`Provider response body is not valid JSON`,
{ cause: e },
);
}
for (const item of data) {
@@ -343,6 +346,7 @@ class GitHubProvider extends Provider {
} catch (e) {
throw new identitiesErrors.ErrorProviderCall(
`Provider response body is not valid JSON`,
{ cause: e },
);
}
for (const item of data) {
@@ -414,6 +418,7 @@ class GitHubProvider extends Provider {
} catch (e) {
throw new identitiesErrors.ErrorProviderCall(
`Provider response body is not valid JSON`,
{ cause: e },
);
}
return {
@@ -466,6 +471,7 @@ class GitHubProvider extends Provider {
} catch (e) {
throw new identitiesErrors.ErrorProviderCall(
`Provider response body is not valid JSON`,
{ cause: e },
);
}
const linkClaimData = data.files[this.gistFilename]?.content;
19 changes: 17 additions & 2 deletions src/keys/KeyManager.ts
Original file line number Diff line number Diff line change
@@ -275,6 +275,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
try {
@@ -422,6 +423,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
await this.garbageCollectRootCerts();
@@ -545,6 +547,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
}
@@ -642,6 +645,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
return true;
@@ -663,6 +667,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
let keyPair;
@@ -675,7 +680,7 @@ class KeyManager {
password,
);
} catch (e) {
throw new keysErrors.ErrorRootKeysParse(e.message);
throw new keysErrors.ErrorRootKeysParse(e.message, { cause: e });
}
return keyPair;
}
@@ -709,6 +714,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
}
@@ -735,6 +741,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
const rootKeyPairBits = keysUtils.publicKeyBitSize(
@@ -784,6 +791,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
return true;
@@ -802,6 +810,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
let keysDbKeyPlain;
@@ -811,7 +820,7 @@ class KeyManager {
keysDbKeyCipher,
);
} catch (e) {
throw new keysErrors.ErrorDBKeyParse(e.message);
throw new keysErrors.ErrorDBKeyParse(e.message, { cause: e });
}
return keysDbKeyPlain;
}
@@ -838,6 +847,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
}
@@ -881,6 +891,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
return true;
@@ -901,6 +912,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
const rootCert = keysUtils.certFromPem(rootCertPem);
@@ -924,6 +936,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
}
@@ -945,6 +958,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
rootCertsNames.sort((a, b) => {
@@ -984,6 +998,7 @@ class KeyManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
return rootCertsPems;
1 change: 1 addition & 0 deletions src/network/ConnectionForward.ts
Original file line number Diff line number Diff line change
@@ -170,6 +170,7 @@ class ConnectionForward extends Connection {
errno: e.errno,
syscall: e.syscall,
},
cause: e,
});
} finally {
clearInterval(punchInterval);
2 changes: 2 additions & 0 deletions src/network/ConnectionReverse.ts
Original file line number Diff line number Diff line change
@@ -162,6 +162,7 @@ class ConnectionReverse extends Connection {
errno: e.errno,
syscall: e.syscall,
},
cause: e,
});
} finally {
clearInterval(punchInterval);
@@ -254,6 +255,7 @@ class ConnectionReverse extends Connection {
errno: e.errno,
syscall: e.syscall,
},
cause: e,
});
}
tlsSocket.on('error', async (e) => {
2 changes: 1 addition & 1 deletion src/network/utils.ts
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ async function resolveHost(host: Host | Hostname): Promise<Host> {
// Resolve the hostname and get the IPv4 address
resolvedHost = await lookup(host, 4);
} catch (e) {
throw new networkErrors.ErrorHostnameResolutionFailed(e.message);
throw new networkErrors.ErrorHostnameResolutionFailed(e.message, { cause: e });
}
// Returns an array of [ resolved address, family (4 or 6) ]
return resolvedHost[0] as Host;
2 changes: 1 addition & 1 deletion src/nodes/NodeConnection.ts
Original file line number Diff line number Diff line change
@@ -135,7 +135,7 @@ class NodeConnection<T extends GRPCClient> {
await nodeConnection.destroy();
// If the connection times out, re-throw this with a higher level nodes exception
if (e instanceof grpcErrors.ErrorGRPCClientTimeout) {
throw new nodesErrors.ErrorNodeConnectionTimeout();
throw new nodesErrors.ErrorNodeConnectionTimeout(e.message, { cause: e });
}
throw e;
}
2 changes: 1 addition & 1 deletion src/notifications/utils.ts
Original file line number Diff line number Diff line change
@@ -78,7 +78,7 @@ async function verifyAndDecodeNotif(notifJWT: string): Promise<Notification> {
throw err;
} else {
// Error came from jose
throw new notificationsErrors.ErrorNotificationsParse();
throw new notificationsErrors.ErrorNotificationsParse(err.message, { cause: err });
}
}
}
5 changes: 5 additions & 0 deletions src/schema/Schema.ts
Original file line number Diff line number Diff line change
@@ -88,6 +88,7 @@ class Schema {
code: e.code,
path: e.path,
},
cause: e,
});
}
}
@@ -101,6 +102,7 @@ class Schema {
code: e.code,
path: e.path,
},
cause: e,
});
}
const stateVersion = await this.readVersion();
@@ -136,6 +138,7 @@ class Schema {
code: e.code,
path: e.path,
},
cause: e,
});
}
this.logger.info(`Destroyed ${this.constructor.name}`);
@@ -160,6 +163,7 @@ class Schema {
code: e.code,
path: e.path,
},
cause: e,
});
}
const stateVersion = parseInt(stateVersionData.trim());
@@ -186,6 +190,7 @@ class Schema {
code: e.code,
path: e.path,
},
cause: e,
});
}
});
12 changes: 9 additions & 3 deletions src/status/Status.ts
Original file line number Diff line number Diff line change
@@ -118,6 +118,7 @@ class Status {
code: e.code,
path: e.path,
},
cause: e,
});
}
while (!lock(statusFile.fd)) {
@@ -134,6 +135,7 @@ class Status {
code: e.code,
path: e.path,
},
cause: e,
});
}
if (statusData === '') {
@@ -143,7 +145,7 @@ class Status {
try {
statusInfo = JSON.parse(statusData, this.statusReviver);
} catch (e) {
throw new statusErrors.ErrorStatusParse('JSON parsing failed');
throw new statusErrors.ErrorStatusParse('JSON parsing failed', {cause: e});
}
if (!statusUtils.statusValidate(statusInfo)) {
throw new statusErrors.ErrorStatusParse(
@@ -192,6 +194,7 @@ class Status {
code: e.code,
path: e.path,
},
cause: e,
});
}
} finally {
@@ -219,6 +222,7 @@ class Status {
code: e.code,
path: e.path,
},
cause: e,
});
}
while (!lock(statusFile.fd)) {
@@ -235,13 +239,14 @@ class Status {
code: e.code,
path: e.path,
},
cause: e,
});
}
let statusInfo;
try {
statusInfo = JSON.parse(statusData, this.statusReviver);
} catch (e) {
throw new statusErrors.ErrorStatusParse('JSON parsing failed');
throw new statusErrors.ErrorStatusParse('JSON parsing failed', { cause: e });
}
if (!statusUtils.statusValidate(statusInfo)) {
throw new statusErrors.ErrorStatusParse(
@@ -272,6 +277,7 @@ class Status {
code: e.code,
path: e.path,
},
cause: e,
});
}
return statusInfo;
@@ -311,7 +317,7 @@ class Status {
);
} catch (e) {
if (e instanceof errors.ErrorUtilsPollTimeout) {
throw new errors.ErrorStatusTimeout();
throw new errors.ErrorStatusTimeout(e.message, { cause: e });
}
throw e;
}
2 changes: 2 additions & 0 deletions src/validation/utils.ts
Original file line number Diff line number Diff line change
@@ -227,6 +227,7 @@ function parseSeedNodes(data: any): [SeedNodes, boolean] {
if (e instanceof TypeError) {
throw new validationErrors.ErrorParse(
'Seed nodes must be of format `nodeId@host:port;...`',
{ cause: e },
);
}
throw e;
@@ -245,6 +246,7 @@ function parseSeedNodes(data: any): [SeedNodes, boolean] {
if (e instanceof validationErrors.ErrorParse) {
throw new validationErrors.ErrorParse(
'Seed nodes must be of format `nodeId@host:port;...`',
{ cause: e },
);
}
throw e;
4 changes: 2 additions & 2 deletions src/vaults/VaultInternal.ts
Original file line number Diff line number Diff line change
@@ -376,7 +376,7 @@ class VaultInternal {
e instanceof git.Errors.NotFoundError ||
e instanceof git.Errors.CommitNotFetchedError
) {
throw new vaultsErrors.ErrorVaultReferenceMissing();
throw new vaultsErrors.ErrorVaultReferenceMissing(e.message, { cause: e });
}
throw e;
}
@@ -551,7 +551,7 @@ class VaultInternal {
if (err instanceof git.Errors.SmartHttpError && error) {
throw error;
} else if (err instanceof git.Errors.MergeNotSupportedError) {
throw new vaultsErrors.ErrorVaultsMergeConflict();
throw new vaultsErrors.ErrorVaultsMergeConflict(err.message, { cause: err });
}
throw err;
}
4 changes: 3 additions & 1 deletion src/vaults/VaultManager.ts
Original file line number Diff line number Diff line change
@@ -196,7 +196,7 @@ class VaultManager {
});
} catch (e) {
if (e instanceof encryptedFsErrors.ErrorEncryptedFSKey) {
throw new vaultsErrors.ErrorVaultManagerKey();
throw new vaultsErrors.ErrorVaultManagerKey(e.message, { cause: e });
}
throw new vaultsErrors.ErrorVaultManagerEFS(e.message, {
data: {
@@ -205,6 +205,7 @@ class VaultManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
this.vaultsDb = vaultsDb;
@@ -942,6 +943,7 @@ class VaultManager {
code: e.code,
path: e.path,
},
cause: e,
});
}
}
3 changes: 3 additions & 0 deletions src/vaults/VaultOps.ts
Original file line number Diff line number Diff line change
@@ -109,6 +109,7 @@ async function getSecret(vault: Vault, secretName: string): Promise<Buffer> {
if (err.code === 'ENOENT') {
throw new vaultsErrors.ErrorSecretsSecretUndefined(
`Secret with name: ${secretName} does not exist`,
{ cause: err },
);
}
throw err;
@@ -124,6 +125,7 @@ async function statSecret(vault: Vault, secretName: string): Promise<Stat> {
if (err.code === 'ENOENT') {
throw new vaultsErrors.ErrorSecretsSecretUndefined(
`Secret with name: ${secretName} does not exist`,
{ cause: err },
);
}
throw err;
@@ -178,6 +180,7 @@ async function mkdir(
if (err.code === 'ENOENT' && !recursive) {
throw new vaultsErrors.ErrorVaultsRecursive(
`Could not create directory '${dirPath}' without recursive option`,
{ cause: err },
);
}
}

0 comments on commit b14b240

Please sign in to comment.