function stringifyErrorSafely(error) {
    try {

        // 1) Create basic structure.
        // Raw Error does not have 'own' properties, so be explicit about core name/message/stack
        // Order here intentional for serialization
        let ret = {
            name: error.name,
            message: error.message
        };
        Object.assign(ret, error);
        ret.stack = error.stack?.split(/\n/g);

        ret = omitBy(ret, isNil);

        // 2) Deep clone/protect against circularity/monstrosity
        ret = cloneAndTrim(ret);

        // 3) Additional ad-hoc cleanups
        // Remove noisy grails exception wrapper info
        // Remove verbose loadSpec from fetchOptions
        const {serverDetails} = ret;
        if (serverDetails?.className === 'GrailsCompressingFilter') {
            delete serverDetails.className;
            delete serverDetails.lineNumber;
        }

        const {fetchOptions} = ret;
        if (fetchOptions?.loadSpec) {
            fetchOptions.loadType = fetchOptions.loadSpec.typeDisplay;
            fetchOptions.loadNumber = fetchOptions.loadSpec.loadNumber;
            delete fetchOptions.loadSpec;
        }

        // 4) Stringify and cleanse
        return stripTags(JSON.stringify(ret, null, 4));

    } catch (e) {
        const message = 'Failed to serialize error';
        console.error(message, error, e);
        return JSON.stringify({message}, null, 4);
    }
}
/**
 * Serialize an error object safely for submission to server, or user display.
 * This method will avoid circular references and will trim the depth of the object.
 *
 * @param {Error} error
 * @return string
 */
Serialize an error object safely for submission to server, or user display.
This method will avoid circular references and will trim the depth of the object.

@param {Error} error
@return string
Serialize an error object safely for submission to server or user display . This method will avoid circular references and will trim the depth of the object . @param { Error } error @return string
function stringifyErrorSafely(error) {
    try {
        let ret = {
            name: error.name,
            message: error.message
        };
        Object.assign(ret, error);
        ret.stack = error.stack?.split(/\n/g);
        ret = omitBy(ret, isNil);
        ret = cloneAndTrim(ret);
        const {serverDetails} = ret;
        if (serverDetails?.className === 'GrailsCompressingFilter') {
            delete serverDetails.className;
            delete serverDetails.lineNumber;
        }
        const {fetchOptions} = ret;
        if (fetchOptions?.loadSpec) {
            fetchOptions.loadType = fetchOptions.loadSpec.typeDisplay;
            fetchOptions.loadNumber = fetchOptions.loadSpec.loadNumber;
            delete fetchOptions.loadSpec;
        }
        return stripTags(JSON.stringify(ret, null, 4));
    } catch (e) {
        const message = 'Failed to serialize error';
        console.error(message, error, e);
        return JSON.stringify({message}, null, 4);
    }
}
function stringifyErrorSafely ( error ) { try { let ret = { name : error . name , message : error . message } ; Object . assign ( ret , error ) ; ret . stack = error . stack ?. split ( / \n / g ) ; ret = omitBy ( ret , isNil ) ; ret = cloneAndTrim ( ret ) ; const { serverDetails } = ret ; if ( serverDetails ?. className === 'GrailsCompressingFilter' ) { delete serverDetails . className ; delete serverDetails . lineNumber ; } const { fetchOptions } = ret ; if ( fetchOptions ?. loadSpec ) { fetchOptions . loadType = fetchOptions . loadSpec . typeDisplay ; fetchOptions . loadNumber = fetchOptions . loadSpec . loadNumber ; delete fetchOptions . loadSpec ; } return stripTags ( JSON . stringify ( ret , null , 4 ) ) ; } catch ( e ) { const message = 'Failed to serialize error' ; console . error ( message , error , e ) ; return JSON . stringify ( { message } , null , 4 ) ; } }
Serialize an error object safely for submission to server, or user display.
Serialize an error object safely for submission to server or user display .
// 1) Create basic structure. // Raw Error does not have 'own' properties, so be explicit about core name/message/stack // Order here intentional for serialization // 2) Deep clone/protect against circularity/monstrosity // 3) Additional ad-hoc cleanups // Remove noisy grails exception wrapper info // Remove verbose loadSpec from fetchOptions // 4) Stringify and cleanse