@@ -234,14 +234,19 @@ describe('flattenErrorCauses', () => {
234234 expect ( errorCauses ) . toEqual ( undefined )
235235 } )
236236
237- it ( 'should return undefined if cause is not of type Error ' , ( ) => {
237+ it ( 'should support non-Error causes with consistent structure ' , ( ) => {
238238 const error = new Error ( 'foo' ) as ErrorWithCause
239- const nestedError = { biz : 'buz' , cause : new Error ( 'boo' ) } as unknown as Error
240-
239+ const nestedError = { biz : 'buz' , cause : new Error ( 'boo' ) }
241240 error . cause = nestedError
242241
243242 const errorCauses = flattenErrorCauses ( error , ErrorSource . LOGGER )
244- expect ( errorCauses ?. length ) . toEqual ( undefined )
243+ expect ( errorCauses ?. length ) . toEqual ( 1 )
244+ expect ( errorCauses ?. [ 0 ] ) . toEqual ( {
245+ message : '{"biz":"buz","cause":{}}' , // JSON stringified, cause is sanitized
246+ source : ErrorSource . LOGGER ,
247+ type : 'object' ,
248+ stack : undefined ,
249+ } )
245250 } )
246251
247252 it ( 'should use error to extract stack trace' , ( ) => {
@@ -259,6 +264,96 @@ describe('flattenErrorCauses', () => {
259264 const errorCauses = flattenErrorCauses ( error , ErrorSource . LOGGER )
260265 expect ( errorCauses ?. length ) . toEqual ( 10 )
261266 } )
267+
268+ describe ( 'with non-Error values' , ( ) => {
269+ it ( 'should handle string cause with consistent structure' , ( ) => {
270+ const error = new Error ( 'main' ) as ErrorWithCause
271+ error . cause = 'string cause'
272+
273+ const causes = flattenErrorCauses ( error , ErrorSource . CUSTOM )
274+ expect ( causes ?. length ) . toBe ( 1 )
275+ expect ( causes ?. [ 0 ] ) . toEqual ( {
276+ message : '"string cause"' , // JSON stringified
277+ source : ErrorSource . CUSTOM ,
278+ type : 'string' ,
279+ stack : undefined ,
280+ } )
281+ } )
282+
283+ it ( 'should handle object cause with consistent structure' , ( ) => {
284+ const error = new Error ( 'main' ) as ErrorWithCause
285+ error . cause = { code : 'ERR_001' , details : 'Invalid input' }
286+
287+ const causes = flattenErrorCauses ( error , ErrorSource . CUSTOM )
288+ expect ( causes ?. length ) . toBe ( 1 )
289+ expect ( causes ?. [ 0 ] ) . toEqual ( {
290+ message : '{"code":"ERR_001","details":"Invalid input"}' ,
291+ source : ErrorSource . CUSTOM ,
292+ type : 'object' ,
293+ stack : undefined ,
294+ } )
295+ } )
296+
297+ it ( 'should handle number cause with consistent structure' , ( ) => {
298+ const error = new Error ( 'main' ) as ErrorWithCause
299+ error . cause = 42
300+
301+ const causes = flattenErrorCauses ( error , ErrorSource . CUSTOM )
302+ expect ( causes ?. length ) . toBe ( 1 )
303+ expect ( causes ?. [ 0 ] ) . toEqual ( {
304+ message : '42' ,
305+ source : ErrorSource . CUSTOM ,
306+ type : 'number' ,
307+ stack : undefined ,
308+ } )
309+ } )
310+
311+ it ( 'should handle mixed Error and non-Error chain' , ( ) => {
312+ const error1 = new Error ( 'first' ) as ErrorWithCause
313+ const error2 = new Error ( 'second' ) as ErrorWithCause
314+ error1 . cause = error2
315+ error2 . cause = { code : 'ERR_ROOT' }
316+
317+ const causes = flattenErrorCauses ( error1 , ErrorSource . CUSTOM )
318+ expect ( causes ?. length ) . toBe ( 2 )
319+
320+ // First cause: Error with full structure
321+ expect ( causes ?. [ 0 ] . message ) . toBe ( 'second' )
322+ expect ( causes ?. [ 0 ] . type ) . toBe ( 'Error' )
323+ expect ( causes ?. [ 0 ] . stack ) . toContain ( 'Error' )
324+
325+ // Second cause: Object with normalized structure
326+ expect ( causes ?. [ 1 ] ) . toEqual ( {
327+ message : '{"code":"ERR_ROOT"}' ,
328+ source : ErrorSource . CUSTOM ,
329+ type : 'object' ,
330+ stack : undefined ,
331+ } )
332+ } )
333+
334+ it ( 'should stop chain after non-Error cause' , ( ) => {
335+ const error = new Error ( 'main' ) as ErrorWithCause
336+ error . cause = { value : 'data' , cause : new Error ( 'ignored' ) }
337+
338+ const causes = flattenErrorCauses ( error , ErrorSource . CUSTOM )
339+ expect ( causes ?. length ) . toBe ( 1 )
340+ // The entire object is captured, nested cause is sanitized
341+ expect ( causes ?. [ 0 ] . message ) . toContain ( '"value":"data"' )
342+ expect ( causes ?. [ 0 ] . type ) . toBe ( 'object' )
343+ } )
344+
345+ it ( 'should handle null cause' , ( ) => {
346+ const error = new Error ( 'main' ) as ErrorWithCause
347+ error . cause = null
348+ expect ( flattenErrorCauses ( error , ErrorSource . CUSTOM ) ) . toBeUndefined ( )
349+ } )
350+
351+ it ( 'should handle undefined cause' , ( ) => {
352+ const error = new Error ( 'main' ) as ErrorWithCause
353+ error . cause = undefined
354+ expect ( flattenErrorCauses ( error , ErrorSource . CUSTOM ) ) . toBeUndefined ( )
355+ } )
356+ } )
262357} )
263358
264359describe ( 'isError' , ( ) => {
0 commit comments