diff --git a/libraries/o-error/README.md b/libraries/o-error/README.md
index e5944432ea..cf6582b854 100644
--- a/libraries/o-error/README.md
+++ b/libraries/o-error/README.md
@@ -442,7 +442,7 @@ async function cleanup() {
### OError.getFullInfo(error) ⇒ Object
-The merged info from any `tag`s on the given error.
+The merged info from any `tag`s and causes on the given error.
If an info property is repeated, the last one wins.
@@ -450,7 +450,7 @@ If an info property is repeated, the last one wins.
| Param | Type | Description |
| --- | --- | --- |
-| error | Error \| null \| undefined | any errror (may or may not be an `OError`) |
+| error | Error \| null \| undefined | any error (may or may not be an `OError`) |
diff --git a/libraries/o-error/index.d.ts b/libraries/o-error/index.d.ts
index 44332e887b..005be4e078 100644
--- a/libraries/o-error/index.d.ts
+++ b/libraries/o-error/index.d.ts
@@ -63,11 +63,11 @@ declare namespace OError {
*/
export function tag(error: Error, message?: string, info?: any): Error;
/**
- * The merged info from any `tag`s on the given error.
+ * The merged info from any `tag`s and causes on the given error.
*
* If an info property is repeated, the last one wins.
*
- * @param {Error | null | undefined} error any errror (may or may not be an `OError`)
+ * @param {Error | null | undefined} error any error (may or may not be an `OError`)
* @return {Object}
*/
export function getFullInfo(error: Error): any;
diff --git a/libraries/o-error/index.js b/libraries/o-error/index.js
index 8af8d1deba..5da737181f 100644
--- a/libraries/o-error/index.js
+++ b/libraries/o-error/index.js
@@ -98,11 +98,11 @@ class OError extends Error {
}
/**
- * The merged info from any `tag`s on the given error.
+ * The merged info from any `tag`s and causes on the given error.
*
* If an info property is repeated, the last one wins.
*
- * @param {Error | null | undefined} error any errror (may or may not be an `OError`)
+ * @param {Error | null | undefined} error any error (may or may not be an `OError`)
* @return {Object}
*/
static getFullInfo(error) {
@@ -112,6 +112,8 @@ class OError extends Error {
const oError = /** @type{OError} */ (error)
+ if (oError.cause) Object.assign(info, OError.getFullInfo(oError.cause))
+
if (typeof oError.info === 'object') Object.assign(info, oError.info)
if (oError._oErrorTags) {
diff --git a/libraries/o-error/test/o-error-util.test.js b/libraries/o-error/test/o-error-util.test.js
index b82c1093e6..67ecf0875e 100644
--- a/libraries/o-error/test/o-error-util.test.js
+++ b/libraries/o-error/test/o-error-util.test.js
@@ -282,12 +282,38 @@ describe('OError.getFullInfo', function () {
})
})
- it('does not merge info from a cause', function () {
+ it('merges info from a cause', function () {
const err1 = new Error('foo')
const err2 = new Error('bar')
err1.cause = err2
err2.info = { userId: 123 }
- expect(OError.getFullInfo(err1)).to.deep.equal({})
+ expect(OError.getFullInfo(err1)).to.deep.equal({ userId: 123 })
+ })
+
+ it('merges info from a nested cause', function () {
+ const err1 = new Error('foo')
+ const err2 = new Error('bar')
+ const err3 = new Error('baz')
+ err1.cause = err2
+ err2.info = { userId: 123 }
+ err2.cause = err3
+ err3.info = { foo: 42 }
+ expect(OError.getFullInfo(err1)).to.deep.equal({
+ userId: 123,
+ foo: 42,
+ })
+ })
+
+ it('merges info from cause with duplicate keys', function () {
+ const err1 = new Error('foo')
+ const err2 = new Error('bar')
+ err1.info = { userId: 42, foo: 1337 }
+ err1.cause = err2
+ err2.info = { userId: 1 }
+ expect(OError.getFullInfo(err1)).to.deep.equal({
+ userId: 42,
+ foo: 1337,
+ })
})
it('merges info from tags with duplicate keys', function () {
@@ -371,8 +397,8 @@ describe('OError.getFullStack', function () {
' TaggedError: failed to foo',
])
- // The info from the wrapped cause should not leak out.
- expect(OError.getFullInfo(error)).to.eql({ bat: 1 })
+ // The info from the wrapped cause should be picked up for logging.
+ expect(OError.getFullInfo(error)).to.eql({ bat: 1, foo: 1 })
// But it should still be recorded.
expect(OError.getFullInfo(error.cause)).to.eql({ foo: 1 })