[{"data":1,"prerenderedAt":3175},["ShallowReactive",2],{"page-\u002Fjs\u002F18-error-handling":3},{"id":4,"title":5,"body":6,"description":3168,"extension":3169,"meta":3170,"navigation":141,"path":3171,"seo":3172,"stem":3173,"__hash__":3174},"content\u002Fjs\u002F18-error-handling.md","JavaScript 18 — Error Handling Architecture: Custom Errors, Async & Stack Traces",{"type":7,"value":8,"toc":3157},"minimark",[9,14,24,368,372,1108,1112,1687,1691,1883,1887,2280,2284,2620,2624,2919,2923,2927,3061,3153],[10,11,13],"h1",{"id":12},"_18-error-handling-architecture-custom-errors-async-stack-traces","18 — Error Handling Architecture: Custom Errors, Async & Stack Traces",[15,16,18,19,23],"h2",{"id":17},"the-error-object-internals","The ",[20,21,22],"code",{},"Error"," Object Internals",[25,26,28],"code-wrapper",{"language":27},"javascript",[29,30,34],"pre",{"className":31,"code":32,"language":27,"meta":33,"style":33},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F ── The Error object has: name, message, stack (and optionally cause) ──\nconst err = new Error(\"something went wrong\");\nconsole.log(err.name);    \u002F\u002F \"Error\"\nconsole.log(err.message); \u002F\u002F \"something went wrong\"\nconsole.log(err.stack);   \u002F\u002F \"Error: something went wrong\\n    at file.js:1:13\\n    at ...\"\n\u002F\u002F stack is a string (non-standard format, varies by engine)\n\u002F\u002F In V8: includes the call stack frames\n\u002F\u002F In modern engines: stack is a getter (lazily computed, can be modified)\n\n\u002F\u002F ── Error subclasses (built-in) ──\n\u002F\u002F TypeError, RangeError, SyntaxError, ReferenceError, URIError, EvalError\ntry { null.x } catch (e) { console.log(e instanceof TypeError); }  \u002F\u002F true\ntry { [].length = -1 } catch (e) { console.log(e instanceof RangeError); }  \u002F\u002F true\ntry { eval(\"if (true) {\") } catch (e) { console.log(e instanceof SyntaxError); }  \u002F\u002F true\ntry { undeclaredVar } catch (e) { console.log(e instanceof ReferenceError); }  \u002F\u002F true\n\n\u002F\u002F ── Error.cause (ES2022) — chain errors for better debugging ──\ntry {\n    JSON.parse(invalidJson);\n} catch (originalError) {\n    throw new Error(\"Failed to parse config file\", { cause: originalError });\n    \u002F\u002F cause preserves the original error (stack trace chain)\n}\n\u002F\u002F Caller can access: err.cause → the original SyntaxError\n","",[20,35,36,45,77,92,105,118,124,130,136,143,149,155,187,226,262,287,292,298,306,321,332,350,356,362],{"__ignoreMap":33},[37,38,41],"span",{"class":39,"line":40},"line",1,[37,42,44],{"class":43},"sdCPZ","\u002F\u002F ── The Error object has: name, message, stack (and optionally cause) ──\n",[37,46,48,52,56,59,62,66,70,74],{"class":39,"line":47},2,[37,49,51],{"class":50},"svdQ7","const",[37,53,55],{"class":54},"snvgF"," err",[37,57,58],{"class":50}," =",[37,60,61],{"class":50}," new",[37,63,65],{"class":64},"sIsaT"," Error",[37,67,69],{"class":68},"ssxIu","(",[37,71,73],{"class":72},"sJ6F3","\"something went wrong\"",[37,75,76],{"class":68},");\n",[37,78,80,83,86,89],{"class":39,"line":79},3,[37,81,82],{"class":68},"console.",[37,84,85],{"class":64},"log",[37,87,88],{"class":68},"(err.name);    ",[37,90,91],{"class":43},"\u002F\u002F \"Error\"\n",[37,93,95,97,99,102],{"class":39,"line":94},4,[37,96,82],{"class":68},[37,98,85],{"class":64},[37,100,101],{"class":68},"(err.message); ",[37,103,104],{"class":43},"\u002F\u002F \"something went wrong\"\n",[37,106,108,110,112,115],{"class":39,"line":107},5,[37,109,82],{"class":68},[37,111,85],{"class":64},[37,113,114],{"class":68},"(err.stack);   ",[37,116,117],{"class":43},"\u002F\u002F \"Error: something went wrong\\n    at file.js:1:13\\n    at ...\"\n",[37,119,121],{"class":39,"line":120},6,[37,122,123],{"class":43},"\u002F\u002F stack is a string (non-standard format, varies by engine)\n",[37,125,127],{"class":39,"line":126},7,[37,128,129],{"class":43},"\u002F\u002F In V8: includes the call stack frames\n",[37,131,133],{"class":39,"line":132},8,[37,134,135],{"class":43},"\u002F\u002F In modern engines: stack is a getter (lazily computed, can be modified)\n",[37,137,139],{"class":39,"line":138},9,[37,140,142],{"emptyLinePlaceholder":141},true,"\n",[37,144,146],{"class":39,"line":145},10,[37,147,148],{"class":43},"\u002F\u002F ── Error subclasses (built-in) ──\n",[37,150,152],{"class":39,"line":151},11,[37,153,154],{"class":43},"\u002F\u002F TypeError, RangeError, SyntaxError, ReferenceError, URIError, EvalError\n",[37,156,158,161,164,167,170,172,175,178,181,184],{"class":39,"line":157},12,[37,159,160],{"class":50},"try",[37,162,163],{"class":68}," { null.x } ",[37,165,166],{"class":50},"catch",[37,168,169],{"class":68}," (e) { console.",[37,171,85],{"class":64},[37,173,174],{"class":68},"(e ",[37,176,177],{"class":50},"instanceof",[37,179,180],{"class":64}," TypeError",[37,182,183],{"class":68},"); }  ",[37,185,186],{"class":43},"\u002F\u002F true\n",[37,188,190,192,195,198,200,203,206,209,211,213,215,217,219,222,224],{"class":39,"line":189},13,[37,191,160],{"class":50},[37,193,194],{"class":68}," { [].",[37,196,197],{"class":54},"length",[37,199,58],{"class":50},[37,201,202],{"class":50}," -",[37,204,205],{"class":54},"1",[37,207,208],{"class":68}," } ",[37,210,166],{"class":50},[37,212,169],{"class":68},[37,214,85],{"class":64},[37,216,174],{"class":68},[37,218,177],{"class":50},[37,220,221],{"class":64}," RangeError",[37,223,183],{"class":68},[37,225,186],{"class":43},[37,227,229,231,234,237,239,242,245,247,249,251,253,255,258,260],{"class":39,"line":228},14,[37,230,160],{"class":50},[37,232,233],{"class":68}," { ",[37,235,236],{"class":64},"eval",[37,238,69],{"class":68},[37,240,241],{"class":72},"\"if (true) {\"",[37,243,244],{"class":68},") } ",[37,246,166],{"class":50},[37,248,169],{"class":68},[37,250,85],{"class":64},[37,252,174],{"class":68},[37,254,177],{"class":50},[37,256,257],{"class":64}," SyntaxError",[37,259,183],{"class":68},[37,261,186],{"class":43},[37,263,265,267,270,272,274,276,278,280,283,285],{"class":39,"line":264},15,[37,266,160],{"class":50},[37,268,269],{"class":68}," { undeclaredVar } ",[37,271,166],{"class":50},[37,273,169],{"class":68},[37,275,85],{"class":64},[37,277,174],{"class":68},[37,279,177],{"class":50},[37,281,282],{"class":64}," ReferenceError",[37,284,183],{"class":68},[37,286,186],{"class":43},[37,288,290],{"class":39,"line":289},16,[37,291,142],{"emptyLinePlaceholder":141},[37,293,295],{"class":39,"line":294},17,[37,296,297],{"class":43},"\u002F\u002F ── Error.cause (ES2022) — chain errors for better debugging ──\n",[37,299,301,303],{"class":39,"line":300},18,[37,302,160],{"class":50},[37,304,305],{"class":68}," {\n",[37,307,309,312,315,318],{"class":39,"line":308},19,[37,310,311],{"class":54},"    JSON",[37,313,314],{"class":68},".",[37,316,317],{"class":64},"parse",[37,319,320],{"class":68},"(invalidJson);\n",[37,322,324,327,329],{"class":39,"line":323},20,[37,325,326],{"class":68},"} ",[37,328,166],{"class":50},[37,330,331],{"class":68}," (originalError) {\n",[37,333,335,338,340,342,344,347],{"class":39,"line":334},21,[37,336,337],{"class":50},"    throw",[37,339,61],{"class":50},[37,341,65],{"class":64},[37,343,69],{"class":68},[37,345,346],{"class":72},"\"Failed to parse config file\"",[37,348,349],{"class":68},", { cause: originalError });\n",[37,351,353],{"class":39,"line":352},22,[37,354,355],{"class":43},"    \u002F\u002F cause preserves the original error (stack trace chain)\n",[37,357,359],{"class":39,"line":358},23,[37,360,361],{"class":68},"}\n",[37,363,365],{"class":39,"line":364},24,[37,366,367],{"class":43},"\u002F\u002F Caller can access: err.cause → the original SyntaxError\n",[15,369,371],{"id":370},"custom-error-hierarchy","Custom Error Hierarchy",[25,373,374],{"language":27},[29,375,377],{"className":31,"code":376,"language":27,"meta":33,"style":33},"\u002F\u002F ── Custom error classes for domain-specific errors ──\nclass AppError extends Error {\n    constructor(message, { code, statusCode, cause } = {}) {\n        super(message, { cause });\n        this.name = this.constructor.name;  \u002F\u002F set name to the subclass name\n        this.code = code;                    \u002F\u002F machine-readable error code\n        this.statusCode = statusCode;        \u002F\u002F HTTP status code (for APIs)\n        Error.captureStackTrace?.(this, this.constructor);  \u002F\u002F V8: clean stack (skip this frame)\n    }\n}\n\nclass ValidationError extends AppError {\n    constructor(message, { field, cause } = {}) {\n        super(message, { code: \"VALIDATION_ERROR\", statusCode: 400, cause });\n        this.field = field;  \u002F\u002F which field failed validation\n    }\n}\n\nclass NotFoundError extends AppError {\n    constructor(resource, id) {\n        super(`${resource} not found: ${id}`, {\n            code: \"NOT_FOUND\",\n            statusCode: 404,\n        });\n        this.resource = resource;\n        this.id = id;\n    }\n}\n\nclass DatabaseError extends AppError {\n    constructor(message, { query, cause } = {}) {\n        super(message, { code: \"DATABASE_ERROR\", statusCode: 500, cause });\n        this.query = query;\n    }\n}\n\n\u002F\u002F ── Usage with instanceof (hierarchical error handling) ──\nfunction handleApiError(error) {\n    if (error instanceof ValidationError) {\n        return { status: 400, error: { code: error.code, message: error.message, field: error.field } };\n    }\n    if (error instanceof NotFoundError) {\n        return { status: 404, error: { code: error.code, message: error.message } };\n    }\n    if (error instanceof DatabaseError) {\n        console.error(\"DB error:\", error.cause);  \u002F\u002F log the original cause\n        return { status: 500, error: { code: \"INTERNAL_ERROR\", message: \"database error\" } };\n    }\n    \u002F\u002F Fallback for unknown errors\n    console.error(\"unexpected error:\", error);\n    return { status: 500, error: { code: \"INTERNAL_ERROR\", message: \"unexpected error\" } };\n}\n\n\u002F\u002F ── Throwing and catching ──\ntry {\n    throw new ValidationError(\"invalid email\", { field: \"email\" });\n} catch (error) {\n    if (error instanceof ValidationError) {\n        console.log(\"validation failed:\", error.field);  \u002F\u002F \"email\"\n    }\n}\n",[20,378,379,384,399,434,442,466,481,496,524,529,533,537,550,573,592,607,611,615,619,632,649,671,682,692,697,710,723,728,733,738,752,776,793,806,811,816,821,827,843,858,872,877,890,902,907,920,939,963,968,974,990,1011,1016,1021,1027,1034,1057,1067,1080,1098,1103],{"__ignoreMap":33},[37,380,381],{"class":39,"line":40},[37,382,383],{"class":43},"\u002F\u002F ── Custom error classes for domain-specific errors ──\n",[37,385,386,389,392,395,397],{"class":39,"line":47},[37,387,388],{"class":50},"class",[37,390,391],{"class":64}," AppError",[37,393,394],{"class":50}," extends",[37,396,65],{"class":64},[37,398,305],{"class":68},[37,400,401,404,406,410,413,415,418,421,423,426,428,431],{"class":39,"line":79},[37,402,403],{"class":50},"    constructor",[37,405,69],{"class":68},[37,407,409],{"class":408},"sCrzJ","message",[37,411,412],{"class":68},", { ",[37,414,20],{"class":408},[37,416,417],{"class":68},", ",[37,419,420],{"class":408},"statusCode",[37,422,417],{"class":68},[37,424,425],{"class":408},"cause",[37,427,208],{"class":68},[37,429,430],{"class":50},"=",[37,432,433],{"class":68}," {}) {\n",[37,435,436,439],{"class":39,"line":94},[37,437,438],{"class":54},"        super",[37,440,441],{"class":68},"(message, { cause });\n",[37,443,444,447,450,452,455,457,460,463],{"class":39,"line":107},[37,445,446],{"class":54},"        this",[37,448,449],{"class":68},".name ",[37,451,430],{"class":50},[37,453,454],{"class":54}," this",[37,456,314],{"class":68},[37,458,459],{"class":54},"constructor",[37,461,462],{"class":68},".name;  ",[37,464,465],{"class":43},"\u002F\u002F set name to the subclass name\n",[37,467,468,470,473,475,478],{"class":39,"line":120},[37,469,446],{"class":54},[37,471,472],{"class":68},".code ",[37,474,430],{"class":50},[37,476,477],{"class":68}," code;                    ",[37,479,480],{"class":43},"\u002F\u002F machine-readable error code\n",[37,482,483,485,488,490,493],{"class":39,"line":126},[37,484,446],{"class":54},[37,486,487],{"class":68},".statusCode ",[37,489,430],{"class":50},[37,491,492],{"class":68}," statusCode;        ",[37,494,495],{"class":43},"\u002F\u002F HTTP status code (for APIs)\n",[37,497,498,501,504,507,510,512,514,516,518,521],{"class":39,"line":132},[37,499,500],{"class":68},"        Error.",[37,502,503],{"class":64},"captureStackTrace",[37,505,506],{"class":68},"?.(",[37,508,509],{"class":54},"this",[37,511,417],{"class":68},[37,513,509],{"class":54},[37,515,314],{"class":68},[37,517,459],{"class":54},[37,519,520],{"class":68},");  ",[37,522,523],{"class":43},"\u002F\u002F V8: clean stack (skip this frame)\n",[37,525,526],{"class":39,"line":138},[37,527,528],{"class":68},"    }\n",[37,530,531],{"class":39,"line":145},[37,532,361],{"class":68},[37,534,535],{"class":39,"line":151},[37,536,142],{"emptyLinePlaceholder":141},[37,538,539,541,544,546,548],{"class":39,"line":157},[37,540,388],{"class":50},[37,542,543],{"class":64}," ValidationError",[37,545,394],{"class":50},[37,547,391],{"class":64},[37,549,305],{"class":68},[37,551,552,554,556,558,560,563,565,567,569,571],{"class":39,"line":189},[37,553,403],{"class":50},[37,555,69],{"class":68},[37,557,409],{"class":408},[37,559,412],{"class":68},[37,561,562],{"class":408},"field",[37,564,417],{"class":68},[37,566,425],{"class":408},[37,568,208],{"class":68},[37,570,430],{"class":50},[37,572,433],{"class":68},[37,574,575,577,580,583,586,589],{"class":39,"line":228},[37,576,438],{"class":54},[37,578,579],{"class":68},"(message, { code: ",[37,581,582],{"class":72},"\"VALIDATION_ERROR\"",[37,584,585],{"class":68},", statusCode: ",[37,587,588],{"class":54},"400",[37,590,591],{"class":68},", cause });\n",[37,593,594,596,599,601,604],{"class":39,"line":264},[37,595,446],{"class":54},[37,597,598],{"class":68},".field ",[37,600,430],{"class":50},[37,602,603],{"class":68}," field;  ",[37,605,606],{"class":43},"\u002F\u002F which field failed validation\n",[37,608,609],{"class":39,"line":289},[37,610,528],{"class":68},[37,612,613],{"class":39,"line":294},[37,614,361],{"class":68},[37,616,617],{"class":39,"line":300},[37,618,142],{"emptyLinePlaceholder":141},[37,620,621,623,626,628,630],{"class":39,"line":308},[37,622,388],{"class":50},[37,624,625],{"class":64}," NotFoundError",[37,627,394],{"class":50},[37,629,391],{"class":64},[37,631,305],{"class":68},[37,633,634,636,638,641,643,646],{"class":39,"line":323},[37,635,403],{"class":50},[37,637,69],{"class":68},[37,639,640],{"class":408},"resource",[37,642,417],{"class":68},[37,644,645],{"class":408},"id",[37,647,648],{"class":68},") {\n",[37,650,651,653,655,658,660,663,665,668],{"class":39,"line":334},[37,652,438],{"class":54},[37,654,69],{"class":68},[37,656,657],{"class":72},"`${",[37,659,640],{"class":68},[37,661,662],{"class":72},"} not found: ${",[37,664,645],{"class":68},[37,666,667],{"class":72},"}`",[37,669,670],{"class":68},", {\n",[37,672,673,676,679],{"class":39,"line":352},[37,674,675],{"class":68},"            code: ",[37,677,678],{"class":72},"\"NOT_FOUND\"",[37,680,681],{"class":68},",\n",[37,683,684,687,690],{"class":39,"line":358},[37,685,686],{"class":68},"            statusCode: ",[37,688,689],{"class":54},"404",[37,691,681],{"class":68},[37,693,694],{"class":39,"line":364},[37,695,696],{"class":68},"        });\n",[37,698,700,702,705,707],{"class":39,"line":699},25,[37,701,446],{"class":54},[37,703,704],{"class":68},".resource ",[37,706,430],{"class":50},[37,708,709],{"class":68}," resource;\n",[37,711,713,715,718,720],{"class":39,"line":712},26,[37,714,446],{"class":54},[37,716,717],{"class":68},".id ",[37,719,430],{"class":50},[37,721,722],{"class":68}," id;\n",[37,724,726],{"class":39,"line":725},27,[37,727,528],{"class":68},[37,729,731],{"class":39,"line":730},28,[37,732,361],{"class":68},[37,734,736],{"class":39,"line":735},29,[37,737,142],{"emptyLinePlaceholder":141},[37,739,741,743,746,748,750],{"class":39,"line":740},30,[37,742,388],{"class":50},[37,744,745],{"class":64}," DatabaseError",[37,747,394],{"class":50},[37,749,391],{"class":64},[37,751,305],{"class":68},[37,753,755,757,759,761,763,766,768,770,772,774],{"class":39,"line":754},31,[37,756,403],{"class":50},[37,758,69],{"class":68},[37,760,409],{"class":408},[37,762,412],{"class":68},[37,764,765],{"class":408},"query",[37,767,417],{"class":68},[37,769,425],{"class":408},[37,771,208],{"class":68},[37,773,430],{"class":50},[37,775,433],{"class":68},[37,777,779,781,783,786,788,791],{"class":39,"line":778},32,[37,780,438],{"class":54},[37,782,579],{"class":68},[37,784,785],{"class":72},"\"DATABASE_ERROR\"",[37,787,585],{"class":68},[37,789,790],{"class":54},"500",[37,792,591],{"class":68},[37,794,796,798,801,803],{"class":39,"line":795},33,[37,797,446],{"class":54},[37,799,800],{"class":68},".query ",[37,802,430],{"class":50},[37,804,805],{"class":68}," query;\n",[37,807,809],{"class":39,"line":808},34,[37,810,528],{"class":68},[37,812,814],{"class":39,"line":813},35,[37,815,361],{"class":68},[37,817,819],{"class":39,"line":818},36,[37,820,142],{"emptyLinePlaceholder":141},[37,822,824],{"class":39,"line":823},37,[37,825,826],{"class":43},"\u002F\u002F ── Usage with instanceof (hierarchical error handling) ──\n",[37,828,830,833,836,838,841],{"class":39,"line":829},38,[37,831,832],{"class":50},"function",[37,834,835],{"class":64}," handleApiError",[37,837,69],{"class":68},[37,839,840],{"class":408},"error",[37,842,648],{"class":68},[37,844,846,849,852,854,856],{"class":39,"line":845},39,[37,847,848],{"class":50},"    if",[37,850,851],{"class":68}," (error ",[37,853,177],{"class":50},[37,855,543],{"class":64},[37,857,648],{"class":68},[37,859,861,864,867,869],{"class":39,"line":860},40,[37,862,863],{"class":50},"        return",[37,865,866],{"class":68}," { status: ",[37,868,588],{"class":54},[37,870,871],{"class":68},", error: { code: error.code, message: error.message, field: error.field } };\n",[37,873,875],{"class":39,"line":874},41,[37,876,528],{"class":68},[37,878,880,882,884,886,888],{"class":39,"line":879},42,[37,881,848],{"class":50},[37,883,851],{"class":68},[37,885,177],{"class":50},[37,887,625],{"class":64},[37,889,648],{"class":68},[37,891,893,895,897,899],{"class":39,"line":892},43,[37,894,863],{"class":50},[37,896,866],{"class":68},[37,898,689],{"class":54},[37,900,901],{"class":68},", error: { code: error.code, message: error.message } };\n",[37,903,905],{"class":39,"line":904},44,[37,906,528],{"class":68},[37,908,910,912,914,916,918],{"class":39,"line":909},45,[37,911,848],{"class":50},[37,913,851],{"class":68},[37,915,177],{"class":50},[37,917,745],{"class":64},[37,919,648],{"class":68},[37,921,923,926,928,930,933,936],{"class":39,"line":922},46,[37,924,925],{"class":68},"        console.",[37,927,840],{"class":64},[37,929,69],{"class":68},[37,931,932],{"class":72},"\"DB error:\"",[37,934,935],{"class":68},", error.cause);  ",[37,937,938],{"class":43},"\u002F\u002F log the original cause\n",[37,940,942,944,946,948,951,954,957,960],{"class":39,"line":941},47,[37,943,863],{"class":50},[37,945,866],{"class":68},[37,947,790],{"class":54},[37,949,950],{"class":68},", error: { code: ",[37,952,953],{"class":72},"\"INTERNAL_ERROR\"",[37,955,956],{"class":68},", message: ",[37,958,959],{"class":72},"\"database error\"",[37,961,962],{"class":68}," } };\n",[37,964,966],{"class":39,"line":965},48,[37,967,528],{"class":68},[37,969,971],{"class":39,"line":970},49,[37,972,973],{"class":43},"    \u002F\u002F Fallback for unknown errors\n",[37,975,977,980,982,984,987],{"class":39,"line":976},50,[37,978,979],{"class":68},"    console.",[37,981,840],{"class":64},[37,983,69],{"class":68},[37,985,986],{"class":72},"\"unexpected error:\"",[37,988,989],{"class":68},", error);\n",[37,991,993,996,998,1000,1002,1004,1006,1009],{"class":39,"line":992},51,[37,994,995],{"class":50},"    return",[37,997,866],{"class":68},[37,999,790],{"class":54},[37,1001,950],{"class":68},[37,1003,953],{"class":72},[37,1005,956],{"class":68},[37,1007,1008],{"class":72},"\"unexpected error\"",[37,1010,962],{"class":68},[37,1012,1014],{"class":39,"line":1013},52,[37,1015,361],{"class":68},[37,1017,1019],{"class":39,"line":1018},53,[37,1020,142],{"emptyLinePlaceholder":141},[37,1022,1024],{"class":39,"line":1023},54,[37,1025,1026],{"class":43},"\u002F\u002F ── Throwing and catching ──\n",[37,1028,1030,1032],{"class":39,"line":1029},55,[37,1031,160],{"class":50},[37,1033,305],{"class":68},[37,1035,1037,1039,1041,1043,1045,1048,1051,1054],{"class":39,"line":1036},56,[37,1038,337],{"class":50},[37,1040,61],{"class":50},[37,1042,543],{"class":64},[37,1044,69],{"class":68},[37,1046,1047],{"class":72},"\"invalid email\"",[37,1049,1050],{"class":68},", { field: ",[37,1052,1053],{"class":72},"\"email\"",[37,1055,1056],{"class":68}," });\n",[37,1058,1060,1062,1064],{"class":39,"line":1059},57,[37,1061,326],{"class":68},[37,1063,166],{"class":50},[37,1065,1066],{"class":68}," (error) {\n",[37,1068,1070,1072,1074,1076,1078],{"class":39,"line":1069},58,[37,1071,848],{"class":50},[37,1073,851],{"class":68},[37,1075,177],{"class":50},[37,1077,543],{"class":64},[37,1079,648],{"class":68},[37,1081,1083,1085,1087,1089,1092,1095],{"class":39,"line":1082},59,[37,1084,925],{"class":68},[37,1086,85],{"class":64},[37,1088,69],{"class":68},[37,1090,1091],{"class":72},"\"validation failed:\"",[37,1093,1094],{"class":68},", error.field);  ",[37,1096,1097],{"class":43},"\u002F\u002F \"email\"\n",[37,1099,1101],{"class":39,"line":1100},60,[37,1102,528],{"class":68},[37,1104,1106],{"class":39,"line":1105},61,[37,1107,361],{"class":68},[15,1109,1111],{"id":1110},"async-error-handling","Async Error Handling",[25,1113,1114],{"language":27},[29,1115,1117],{"className":31,"code":1116,"language":27,"meta":33,"style":33},"\u002F\u002F ── try\u002Fcatch with await (catches async errors) ──\nasync function fetchData(url) {\n    try {\n        const response = await fetch(url);\n        if (!response.ok) {\n            throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n        }\n        return await response.json();\n    } catch (error) {\n        if (error instanceof TypeError) {\n            \u002F\u002F Network error (fetch failed entirely — CORS, DNS, offline)\n            throw new AppError(\"Network request failed\", { code: \"NETWORK_ERROR\", cause: error });\n        }\n        throw error;  \u002F\u002F re-throw HTTP errors and parse errors\n    }\n}\n\n\u002F\u002F ── Promise.catch for error handling (alternative to try\u002Fcatch) ──\nfetchData(url)\n    .then(data => console.log(data))\n    .catch(error => console.error(\"failed:\", error));\n\n\u002F\u002F ── Multiple error types in one catch ──\nasync function processData() {\n    try {\n        const data = await fetchData(\"\u002Fapi\u002Fdata\");\n        const validated = validate(data);  \u002F\u002F might throw ValidationError\n        const saved = await save(validated);  \u002F\u002F might throw DatabaseError\n        return saved;\n    } catch (error) {\n        if (error instanceof ValidationError) {\n            \u002F\u002F Validation error — 400\n            throw error;\n        }\n        if (error instanceof DatabaseError) {\n            \u002F\u002F DB error — 500\n            throw error;\n        }\n        if (error instanceof TypeError) {\n            \u002F\u002F Network error — 503\n            throw new AppError(\"service unavailable\", { code: \"NETWORK_ERROR\", statusCode: 503, cause: error });\n        }\n        \u002F\u002F Unknown error — re-throw\n        throw error;\n    }\n}\n\n\u002F\u002F ── `finally` with async (cleanup that always runs) ──\nasync function withDatabase() {\n    const client = await connectDB();\n    try {\n        return await client.query(\"SELECT * FROM users\");\n    } finally {\n        await client.disconnect();  \u002F\u002F always runs (even if query throws)\n    }\n}\n",[20,1118,1119,1124,1142,1149,1168,1182,1218,1223,1238,1247,1259,1264,1286,1290,1301,1305,1309,1313,1318,1326,1350,1374,1378,1383,1395,1401,1421,1439,1459,1466,1474,1486,1491,1498,1502,1514,1519,1525,1529,1541,1546,1570,1574,1579,1585,1589,1593,1597,1602,1613,1630,1636,1654,1663,1679,1683],{"__ignoreMap":33},[37,1120,1121],{"class":39,"line":40},[37,1122,1123],{"class":43},"\u002F\u002F ── try\u002Fcatch with await (catches async errors) ──\n",[37,1125,1126,1129,1132,1135,1137,1140],{"class":39,"line":47},[37,1127,1128],{"class":50},"async",[37,1130,1131],{"class":50}," function",[37,1133,1134],{"class":64}," fetchData",[37,1136,69],{"class":68},[37,1138,1139],{"class":408},"url",[37,1141,648],{"class":68},[37,1143,1144,1147],{"class":39,"line":79},[37,1145,1146],{"class":50},"    try",[37,1148,305],{"class":68},[37,1150,1151,1154,1157,1159,1162,1165],{"class":39,"line":94},[37,1152,1153],{"class":50},"        const",[37,1155,1156],{"class":54}," response",[37,1158,58],{"class":50},[37,1160,1161],{"class":50}," await",[37,1163,1164],{"class":64}," fetch",[37,1166,1167],{"class":68},"(url);\n",[37,1169,1170,1173,1176,1179],{"class":39,"line":107},[37,1171,1172],{"class":50},"        if",[37,1174,1175],{"class":68}," (",[37,1177,1178],{"class":50},"!",[37,1180,1181],{"class":68},"response.ok) {\n",[37,1183,1184,1187,1189,1191,1193,1196,1199,1201,1204,1207,1209,1211,1214,1216],{"class":39,"line":120},[37,1185,1186],{"class":50},"            throw",[37,1188,61],{"class":50},[37,1190,65],{"class":64},[37,1192,69],{"class":68},[37,1194,1195],{"class":72},"`HTTP ${",[37,1197,1198],{"class":68},"response",[37,1200,314],{"class":72},[37,1202,1203],{"class":68},"status",[37,1205,1206],{"class":72},"}: ${",[37,1208,1198],{"class":68},[37,1210,314],{"class":72},[37,1212,1213],{"class":68},"statusText",[37,1215,667],{"class":72},[37,1217,76],{"class":68},[37,1219,1220],{"class":39,"line":126},[37,1221,1222],{"class":68},"        }\n",[37,1224,1225,1227,1229,1232,1235],{"class":39,"line":132},[37,1226,863],{"class":50},[37,1228,1161],{"class":50},[37,1230,1231],{"class":68}," response.",[37,1233,1234],{"class":64},"json",[37,1236,1237],{"class":68},"();\n",[37,1239,1240,1243,1245],{"class":39,"line":138},[37,1241,1242],{"class":68},"    } ",[37,1244,166],{"class":50},[37,1246,1066],{"class":68},[37,1248,1249,1251,1253,1255,1257],{"class":39,"line":145},[37,1250,1172],{"class":50},[37,1252,851],{"class":68},[37,1254,177],{"class":50},[37,1256,180],{"class":64},[37,1258,648],{"class":68},[37,1260,1261],{"class":39,"line":151},[37,1262,1263],{"class":43},"            \u002F\u002F Network error (fetch failed entirely — CORS, DNS, offline)\n",[37,1265,1266,1268,1270,1272,1274,1277,1280,1283],{"class":39,"line":157},[37,1267,1186],{"class":50},[37,1269,61],{"class":50},[37,1271,391],{"class":64},[37,1273,69],{"class":68},[37,1275,1276],{"class":72},"\"Network request failed\"",[37,1278,1279],{"class":68},", { code: ",[37,1281,1282],{"class":72},"\"NETWORK_ERROR\"",[37,1284,1285],{"class":68},", cause: error });\n",[37,1287,1288],{"class":39,"line":189},[37,1289,1222],{"class":68},[37,1291,1292,1295,1298],{"class":39,"line":228},[37,1293,1294],{"class":50},"        throw",[37,1296,1297],{"class":68}," error;  ",[37,1299,1300],{"class":43},"\u002F\u002F re-throw HTTP errors and parse errors\n",[37,1302,1303],{"class":39,"line":264},[37,1304,528],{"class":68},[37,1306,1307],{"class":39,"line":289},[37,1308,361],{"class":68},[37,1310,1311],{"class":39,"line":294},[37,1312,142],{"emptyLinePlaceholder":141},[37,1314,1315],{"class":39,"line":300},[37,1316,1317],{"class":43},"\u002F\u002F ── Promise.catch for error handling (alternative to try\u002Fcatch) ──\n",[37,1319,1320,1323],{"class":39,"line":308},[37,1321,1322],{"class":64},"fetchData",[37,1324,1325],{"class":68},"(url)\n",[37,1327,1328,1331,1334,1336,1339,1342,1345,1347],{"class":39,"line":323},[37,1329,1330],{"class":68},"    .",[37,1332,1333],{"class":64},"then",[37,1335,69],{"class":68},[37,1337,1338],{"class":408},"data",[37,1340,1341],{"class":50}," =>",[37,1343,1344],{"class":68}," console.",[37,1346,85],{"class":64},[37,1348,1349],{"class":68},"(data))\n",[37,1351,1352,1354,1356,1358,1360,1362,1364,1366,1368,1371],{"class":39,"line":334},[37,1353,1330],{"class":68},[37,1355,166],{"class":64},[37,1357,69],{"class":68},[37,1359,840],{"class":408},[37,1361,1341],{"class":50},[37,1363,1344],{"class":68},[37,1365,840],{"class":64},[37,1367,69],{"class":68},[37,1369,1370],{"class":72},"\"failed:\"",[37,1372,1373],{"class":68},", error));\n",[37,1375,1376],{"class":39,"line":352},[37,1377,142],{"emptyLinePlaceholder":141},[37,1379,1380],{"class":39,"line":358},[37,1381,1382],{"class":43},"\u002F\u002F ── Multiple error types in one catch ──\n",[37,1384,1385,1387,1389,1392],{"class":39,"line":364},[37,1386,1128],{"class":50},[37,1388,1131],{"class":50},[37,1390,1391],{"class":64}," processData",[37,1393,1394],{"class":68},"() {\n",[37,1396,1397,1399],{"class":39,"line":699},[37,1398,1146],{"class":50},[37,1400,305],{"class":68},[37,1402,1403,1405,1408,1410,1412,1414,1416,1419],{"class":39,"line":712},[37,1404,1153],{"class":50},[37,1406,1407],{"class":54}," data",[37,1409,58],{"class":50},[37,1411,1161],{"class":50},[37,1413,1134],{"class":64},[37,1415,69],{"class":68},[37,1417,1418],{"class":72},"\"\u002Fapi\u002Fdata\"",[37,1420,76],{"class":68},[37,1422,1423,1425,1428,1430,1433,1436],{"class":39,"line":725},[37,1424,1153],{"class":50},[37,1426,1427],{"class":54}," validated",[37,1429,58],{"class":50},[37,1431,1432],{"class":64}," validate",[37,1434,1435],{"class":68},"(data);  ",[37,1437,1438],{"class":43},"\u002F\u002F might throw ValidationError\n",[37,1440,1441,1443,1446,1448,1450,1453,1456],{"class":39,"line":730},[37,1442,1153],{"class":50},[37,1444,1445],{"class":54}," saved",[37,1447,58],{"class":50},[37,1449,1161],{"class":50},[37,1451,1452],{"class":64}," save",[37,1454,1455],{"class":68},"(validated);  ",[37,1457,1458],{"class":43},"\u002F\u002F might throw DatabaseError\n",[37,1460,1461,1463],{"class":39,"line":735},[37,1462,863],{"class":50},[37,1464,1465],{"class":68}," saved;\n",[37,1467,1468,1470,1472],{"class":39,"line":740},[37,1469,1242],{"class":68},[37,1471,166],{"class":50},[37,1473,1066],{"class":68},[37,1475,1476,1478,1480,1482,1484],{"class":39,"line":754},[37,1477,1172],{"class":50},[37,1479,851],{"class":68},[37,1481,177],{"class":50},[37,1483,543],{"class":64},[37,1485,648],{"class":68},[37,1487,1488],{"class":39,"line":778},[37,1489,1490],{"class":43},"            \u002F\u002F Validation error — 400\n",[37,1492,1493,1495],{"class":39,"line":795},[37,1494,1186],{"class":50},[37,1496,1497],{"class":68}," error;\n",[37,1499,1500],{"class":39,"line":808},[37,1501,1222],{"class":68},[37,1503,1504,1506,1508,1510,1512],{"class":39,"line":813},[37,1505,1172],{"class":50},[37,1507,851],{"class":68},[37,1509,177],{"class":50},[37,1511,745],{"class":64},[37,1513,648],{"class":68},[37,1515,1516],{"class":39,"line":818},[37,1517,1518],{"class":43},"            \u002F\u002F DB error — 500\n",[37,1520,1521,1523],{"class":39,"line":823},[37,1522,1186],{"class":50},[37,1524,1497],{"class":68},[37,1526,1527],{"class":39,"line":829},[37,1528,1222],{"class":68},[37,1530,1531,1533,1535,1537,1539],{"class":39,"line":845},[37,1532,1172],{"class":50},[37,1534,851],{"class":68},[37,1536,177],{"class":50},[37,1538,180],{"class":64},[37,1540,648],{"class":68},[37,1542,1543],{"class":39,"line":860},[37,1544,1545],{"class":43},"            \u002F\u002F Network error — 503\n",[37,1547,1548,1550,1552,1554,1556,1559,1561,1563,1565,1568],{"class":39,"line":874},[37,1549,1186],{"class":50},[37,1551,61],{"class":50},[37,1553,391],{"class":64},[37,1555,69],{"class":68},[37,1557,1558],{"class":72},"\"service unavailable\"",[37,1560,1279],{"class":68},[37,1562,1282],{"class":72},[37,1564,585],{"class":68},[37,1566,1567],{"class":54},"503",[37,1569,1285],{"class":68},[37,1571,1572],{"class":39,"line":879},[37,1573,1222],{"class":68},[37,1575,1576],{"class":39,"line":892},[37,1577,1578],{"class":43},"        \u002F\u002F Unknown error — re-throw\n",[37,1580,1581,1583],{"class":39,"line":904},[37,1582,1294],{"class":50},[37,1584,1497],{"class":68},[37,1586,1587],{"class":39,"line":909},[37,1588,528],{"class":68},[37,1590,1591],{"class":39,"line":922},[37,1592,361],{"class":68},[37,1594,1595],{"class":39,"line":941},[37,1596,142],{"emptyLinePlaceholder":141},[37,1598,1599],{"class":39,"line":965},[37,1600,1601],{"class":43},"\u002F\u002F ── `finally` with async (cleanup that always runs) ──\n",[37,1603,1604,1606,1608,1611],{"class":39,"line":970},[37,1605,1128],{"class":50},[37,1607,1131],{"class":50},[37,1609,1610],{"class":64}," withDatabase",[37,1612,1394],{"class":68},[37,1614,1615,1618,1621,1623,1625,1628],{"class":39,"line":976},[37,1616,1617],{"class":50},"    const",[37,1619,1620],{"class":54}," client",[37,1622,58],{"class":50},[37,1624,1161],{"class":50},[37,1626,1627],{"class":64}," connectDB",[37,1629,1237],{"class":68},[37,1631,1632,1634],{"class":39,"line":992},[37,1633,1146],{"class":50},[37,1635,305],{"class":68},[37,1637,1638,1640,1642,1645,1647,1649,1652],{"class":39,"line":1013},[37,1639,863],{"class":50},[37,1641,1161],{"class":50},[37,1643,1644],{"class":68}," client.",[37,1646,765],{"class":64},[37,1648,69],{"class":68},[37,1650,1651],{"class":72},"\"SELECT * FROM users\"",[37,1653,76],{"class":68},[37,1655,1656,1658,1661],{"class":39,"line":1018},[37,1657,1242],{"class":68},[37,1659,1660],{"class":50},"finally",[37,1662,305],{"class":68},[37,1664,1665,1668,1670,1673,1676],{"class":39,"line":1023},[37,1666,1667],{"class":50},"        await",[37,1669,1644],{"class":68},[37,1671,1672],{"class":64},"disconnect",[37,1674,1675],{"class":68},"();  ",[37,1677,1678],{"class":43},"\u002F\u002F always runs (even if query throws)\n",[37,1680,1681],{"class":39,"line":1029},[37,1682,528],{"class":68},[37,1684,1685],{"class":39,"line":1036},[37,1686,361],{"class":68},[15,1688,1690],{"id":1689},"anti-pattern-swallowing-errors","Anti-Pattern: Swallowing Errors",[25,1692,1693],{"language":27},[29,1694,1696],{"className":31,"code":1695,"language":27,"meta":33,"style":33},"\u002F\u002F ❌ NAIVE — empty catch swallows errors (makes debugging impossible)\ntry {\n    JSON.parse(data);\n} catch (e) {\n    \u002F\u002F silently ignored — no log, no re-throw, no handling\n}\n\u002F\u002F If the parse fails, the caller has no idea something went wrong.\n\n\u002F\u002F ❌ ALSO BAD — catch with console.log but no re-throw\ntry {\n    JSON.parse(data);\n} catch (e) {\n    console.log(\"error:\", e);  \u002F\u002F logs but continues with undefined data\n}\n\u002F\u002F The function continues with `data` being undefined — downstream code breaks.\n\n\u002F\u002F ✅ CORRECT — handle, re-throw, or provide a fallback\ntry {\n    return JSON.parse(data);\n} catch (e) {\n    \u002F\u002F Option 1: re-throw with context\n    throw new Error(\"Failed to parse data\", { cause: e });\n    \u002F\u002F Option 2: return a safe default\n    \u002F\u002F return {};\n    \u002F\u002F Option 3: log and re-throw\n    \u002F\u002F console.error(\"parse failed:\", e); throw e;\n}\n",[20,1697,1698,1703,1709,1720,1729,1734,1738,1743,1747,1752,1758,1768,1776,1793,1797,1802,1806,1811,1817,1830,1838,1843,1859,1864,1869,1874,1879],{"__ignoreMap":33},[37,1699,1700],{"class":39,"line":40},[37,1701,1702],{"class":43},"\u002F\u002F ❌ NAIVE — empty catch swallows errors (makes debugging impossible)\n",[37,1704,1705,1707],{"class":39,"line":47},[37,1706,160],{"class":50},[37,1708,305],{"class":68},[37,1710,1711,1713,1715,1717],{"class":39,"line":79},[37,1712,311],{"class":54},[37,1714,314],{"class":68},[37,1716,317],{"class":64},[37,1718,1719],{"class":68},"(data);\n",[37,1721,1722,1724,1726],{"class":39,"line":94},[37,1723,326],{"class":68},[37,1725,166],{"class":50},[37,1727,1728],{"class":68}," (e) {\n",[37,1730,1731],{"class":39,"line":107},[37,1732,1733],{"class":43},"    \u002F\u002F silently ignored — no log, no re-throw, no handling\n",[37,1735,1736],{"class":39,"line":120},[37,1737,361],{"class":68},[37,1739,1740],{"class":39,"line":126},[37,1741,1742],{"class":43},"\u002F\u002F If the parse fails, the caller has no idea something went wrong.\n",[37,1744,1745],{"class":39,"line":132},[37,1746,142],{"emptyLinePlaceholder":141},[37,1748,1749],{"class":39,"line":138},[37,1750,1751],{"class":43},"\u002F\u002F ❌ ALSO BAD — catch with console.log but no re-throw\n",[37,1753,1754,1756],{"class":39,"line":145},[37,1755,160],{"class":50},[37,1757,305],{"class":68},[37,1759,1760,1762,1764,1766],{"class":39,"line":151},[37,1761,311],{"class":54},[37,1763,314],{"class":68},[37,1765,317],{"class":64},[37,1767,1719],{"class":68},[37,1769,1770,1772,1774],{"class":39,"line":157},[37,1771,326],{"class":68},[37,1773,166],{"class":50},[37,1775,1728],{"class":68},[37,1777,1778,1780,1782,1784,1787,1790],{"class":39,"line":189},[37,1779,979],{"class":68},[37,1781,85],{"class":64},[37,1783,69],{"class":68},[37,1785,1786],{"class":72},"\"error:\"",[37,1788,1789],{"class":68},", e);  ",[37,1791,1792],{"class":43},"\u002F\u002F logs but continues with undefined data\n",[37,1794,1795],{"class":39,"line":228},[37,1796,361],{"class":68},[37,1798,1799],{"class":39,"line":264},[37,1800,1801],{"class":43},"\u002F\u002F The function continues with `data` being undefined — downstream code breaks.\n",[37,1803,1804],{"class":39,"line":289},[37,1805,142],{"emptyLinePlaceholder":141},[37,1807,1808],{"class":39,"line":294},[37,1809,1810],{"class":43},"\u002F\u002F ✅ CORRECT — handle, re-throw, or provide a fallback\n",[37,1812,1813,1815],{"class":39,"line":300},[37,1814,160],{"class":50},[37,1816,305],{"class":68},[37,1818,1819,1821,1824,1826,1828],{"class":39,"line":308},[37,1820,995],{"class":50},[37,1822,1823],{"class":54}," JSON",[37,1825,314],{"class":68},[37,1827,317],{"class":64},[37,1829,1719],{"class":68},[37,1831,1832,1834,1836],{"class":39,"line":323},[37,1833,326],{"class":68},[37,1835,166],{"class":50},[37,1837,1728],{"class":68},[37,1839,1840],{"class":39,"line":334},[37,1841,1842],{"class":43},"    \u002F\u002F Option 1: re-throw with context\n",[37,1844,1845,1847,1849,1851,1853,1856],{"class":39,"line":352},[37,1846,337],{"class":50},[37,1848,61],{"class":50},[37,1850,65],{"class":64},[37,1852,69],{"class":68},[37,1854,1855],{"class":72},"\"Failed to parse data\"",[37,1857,1858],{"class":68},", { cause: e });\n",[37,1860,1861],{"class":39,"line":358},[37,1862,1863],{"class":43},"    \u002F\u002F Option 2: return a safe default\n",[37,1865,1866],{"class":39,"line":364},[37,1867,1868],{"class":43},"    \u002F\u002F return {};\n",[37,1870,1871],{"class":39,"line":699},[37,1872,1873],{"class":43},"    \u002F\u002F Option 3: log and re-throw\n",[37,1875,1876],{"class":39,"line":712},[37,1877,1878],{"class":43},"    \u002F\u002F console.error(\"parse failed:\", e); throw e;\n",[37,1880,1881],{"class":39,"line":725},[37,1882,361],{"class":68},[15,1884,1886],{"id":1885},"global-error-handlers","Global Error Handlers",[25,1888,1889],{"language":27},[29,1890,1892],{"className":31,"code":1891,"language":27,"meta":33,"style":33},"\u002F\u002F ── Browser: window.onerror (catches uncaught synchronous errors) ──\nwindow.addEventListener(\"error\", (event) => {\n    \u002F\u002F event.error: the Error object\n    \u002F\u002F event.message, event.filename, event.lineno, event.colno\n    console.error(\"Uncaught error:\", event.error);\n    \u002F\u002F Send to error reporting service (Sentry, etc.)\n    reportError(event.error);\n    event.preventDefault();  \u002F\u002F prevent the default error console output\n});\n\n\u002F\u002F ── Browser: unhandledrejection (catches uncaught Promise rejections) ──\nwindow.addEventListener(\"unhandledrejection\", (event) => {\n    console.error(\"Unhandled rejection:\", event.reason);\n    reportError(event.reason);\n    event.preventDefault();  \u002F\u002F prevent console warning\n});\n\n\u002F\u002F ── Node.js: process error events ──\n\u002F\u002F process.on(\"uncaughtException\", (error) => {\n\u002F\u002F     console.error(\"uncaught:\", error);\n\u002F\u002F     \u002F\u002F ⚠️ Don't continue running — the app is in an inconsistent state.\n\u002F\u002F     \u002F\u002F Best practice: log, cleanup, and exit.\n\u002F\u002F     process.exit(1);\n\u002F\u002F });\n\u002F\u002F process.on(\"unhandledRejection\", (reason) => {\n\u002F\u002F     console.error(\"unhandled rejection:\", reason);\n\u002F\u002F     process.exit(1);\n\u002F\u002F });\n\n\u002F\u002F ── Error boundary pattern (React-style) ──\nclass ErrorBoundary {\n    constructor() {\n        this.handlers = [];\n    }\n    catch(fn) {\n        try {\n            return fn();\n        } catch (error) {\n            for (const handler of this.handlers) {\n                if (handler.canHandle(error)) return handler.handle(error);\n            }\n            throw error;\n        }\n    }\n    addHandler(handler) { this.handlers.push(handler); }\n}\n",[20,1893,1894,1899,1926,1931,1936,1950,1955,1963,1976,1981,1985,1990,2011,2025,2032,2043,2047,2051,2056,2061,2066,2074,2081,2086,2091,2096,2101,2105,2109,2113,2118,2127,2133,2145,2149,2161,2168,2178,2187,2207,2233,2238,2244,2248,2252,2276],{"__ignoreMap":33},[37,1895,1896],{"class":39,"line":40},[37,1897,1898],{"class":43},"\u002F\u002F ── Browser: window.onerror (catches uncaught synchronous errors) ──\n",[37,1900,1901,1904,1907,1909,1912,1915,1918,1921,1924],{"class":39,"line":47},[37,1902,1903],{"class":68},"window.",[37,1905,1906],{"class":64},"addEventListener",[37,1908,69],{"class":68},[37,1910,1911],{"class":72},"\"error\"",[37,1913,1914],{"class":68},", (",[37,1916,1917],{"class":408},"event",[37,1919,1920],{"class":68},") ",[37,1922,1923],{"class":50},"=>",[37,1925,305],{"class":68},[37,1927,1928],{"class":39,"line":79},[37,1929,1930],{"class":43},"    \u002F\u002F event.error: the Error object\n",[37,1932,1933],{"class":39,"line":94},[37,1934,1935],{"class":43},"    \u002F\u002F event.message, event.filename, event.lineno, event.colno\n",[37,1937,1938,1940,1942,1944,1947],{"class":39,"line":107},[37,1939,979],{"class":68},[37,1941,840],{"class":64},[37,1943,69],{"class":68},[37,1945,1946],{"class":72},"\"Uncaught error:\"",[37,1948,1949],{"class":68},", event.error);\n",[37,1951,1952],{"class":39,"line":120},[37,1953,1954],{"class":43},"    \u002F\u002F Send to error reporting service (Sentry, etc.)\n",[37,1956,1957,1960],{"class":39,"line":126},[37,1958,1959],{"class":64},"    reportError",[37,1961,1962],{"class":68},"(event.error);\n",[37,1964,1965,1968,1971,1973],{"class":39,"line":132},[37,1966,1967],{"class":68},"    event.",[37,1969,1970],{"class":64},"preventDefault",[37,1972,1675],{"class":68},[37,1974,1975],{"class":43},"\u002F\u002F prevent the default error console output\n",[37,1977,1978],{"class":39,"line":138},[37,1979,1980],{"class":68},"});\n",[37,1982,1983],{"class":39,"line":145},[37,1984,142],{"emptyLinePlaceholder":141},[37,1986,1987],{"class":39,"line":151},[37,1988,1989],{"class":43},"\u002F\u002F ── Browser: unhandledrejection (catches uncaught Promise rejections) ──\n",[37,1991,1992,1994,1996,1998,2001,2003,2005,2007,2009],{"class":39,"line":157},[37,1993,1903],{"class":68},[37,1995,1906],{"class":64},[37,1997,69],{"class":68},[37,1999,2000],{"class":72},"\"unhandledrejection\"",[37,2002,1914],{"class":68},[37,2004,1917],{"class":408},[37,2006,1920],{"class":68},[37,2008,1923],{"class":50},[37,2010,305],{"class":68},[37,2012,2013,2015,2017,2019,2022],{"class":39,"line":189},[37,2014,979],{"class":68},[37,2016,840],{"class":64},[37,2018,69],{"class":68},[37,2020,2021],{"class":72},"\"Unhandled rejection:\"",[37,2023,2024],{"class":68},", event.reason);\n",[37,2026,2027,2029],{"class":39,"line":228},[37,2028,1959],{"class":64},[37,2030,2031],{"class":68},"(event.reason);\n",[37,2033,2034,2036,2038,2040],{"class":39,"line":264},[37,2035,1967],{"class":68},[37,2037,1970],{"class":64},[37,2039,1675],{"class":68},[37,2041,2042],{"class":43},"\u002F\u002F prevent console warning\n",[37,2044,2045],{"class":39,"line":289},[37,2046,1980],{"class":68},[37,2048,2049],{"class":39,"line":294},[37,2050,142],{"emptyLinePlaceholder":141},[37,2052,2053],{"class":39,"line":300},[37,2054,2055],{"class":43},"\u002F\u002F ── Node.js: process error events ──\n",[37,2057,2058],{"class":39,"line":308},[37,2059,2060],{"class":43},"\u002F\u002F process.on(\"uncaughtException\", (error) => {\n",[37,2062,2063],{"class":39,"line":323},[37,2064,2065],{"class":43},"\u002F\u002F     console.error(\"uncaught:\", error);\n",[37,2067,2068,2071],{"class":39,"line":334},[37,2069,2070],{"class":43},"\u002F\u002F",[37,2072,2073],{"class":43},"     \u002F\u002F ⚠️ Don't continue running — the app is in an inconsistent state.\n",[37,2075,2076,2078],{"class":39,"line":352},[37,2077,2070],{"class":43},[37,2079,2080],{"class":43},"     \u002F\u002F Best practice: log, cleanup, and exit.\n",[37,2082,2083],{"class":39,"line":358},[37,2084,2085],{"class":43},"\u002F\u002F     process.exit(1);\n",[37,2087,2088],{"class":39,"line":364},[37,2089,2090],{"class":43},"\u002F\u002F });\n",[37,2092,2093],{"class":39,"line":699},[37,2094,2095],{"class":43},"\u002F\u002F process.on(\"unhandledRejection\", (reason) => {\n",[37,2097,2098],{"class":39,"line":712},[37,2099,2100],{"class":43},"\u002F\u002F     console.error(\"unhandled rejection:\", reason);\n",[37,2102,2103],{"class":39,"line":725},[37,2104,2085],{"class":43},[37,2106,2107],{"class":39,"line":730},[37,2108,2090],{"class":43},[37,2110,2111],{"class":39,"line":735},[37,2112,142],{"emptyLinePlaceholder":141},[37,2114,2115],{"class":39,"line":740},[37,2116,2117],{"class":43},"\u002F\u002F ── Error boundary pattern (React-style) ──\n",[37,2119,2120,2122,2125],{"class":39,"line":754},[37,2121,388],{"class":50},[37,2123,2124],{"class":64}," ErrorBoundary",[37,2126,305],{"class":68},[37,2128,2129,2131],{"class":39,"line":778},[37,2130,403],{"class":50},[37,2132,1394],{"class":68},[37,2134,2135,2137,2140,2142],{"class":39,"line":795},[37,2136,446],{"class":54},[37,2138,2139],{"class":68},".handlers ",[37,2141,430],{"class":50},[37,2143,2144],{"class":68}," [];\n",[37,2146,2147],{"class":39,"line":808},[37,2148,528],{"class":68},[37,2150,2151,2154,2156,2159],{"class":39,"line":813},[37,2152,2153],{"class":64},"    catch",[37,2155,69],{"class":68},[37,2157,2158],{"class":408},"fn",[37,2160,648],{"class":68},[37,2162,2163,2166],{"class":39,"line":818},[37,2164,2165],{"class":50},"        try",[37,2167,305],{"class":68},[37,2169,2170,2173,2176],{"class":39,"line":823},[37,2171,2172],{"class":50},"            return",[37,2174,2175],{"class":64}," fn",[37,2177,1237],{"class":68},[37,2179,2180,2183,2185],{"class":39,"line":829},[37,2181,2182],{"class":68},"        } ",[37,2184,166],{"class":50},[37,2186,1066],{"class":68},[37,2188,2189,2192,2194,2196,2199,2202,2204],{"class":39,"line":845},[37,2190,2191],{"class":50},"            for",[37,2193,1175],{"class":68},[37,2195,51],{"class":50},[37,2197,2198],{"class":54}," handler",[37,2200,2201],{"class":50}," of",[37,2203,454],{"class":54},[37,2205,2206],{"class":68},".handlers) {\n",[37,2208,2209,2212,2215,2218,2221,2224,2227,2230],{"class":39,"line":860},[37,2210,2211],{"class":50},"                if",[37,2213,2214],{"class":68}," (handler.",[37,2216,2217],{"class":64},"canHandle",[37,2219,2220],{"class":68},"(error)) ",[37,2222,2223],{"class":50},"return",[37,2225,2226],{"class":68}," handler.",[37,2228,2229],{"class":64},"handle",[37,2231,2232],{"class":68},"(error);\n",[37,2234,2235],{"class":39,"line":874},[37,2236,2237],{"class":68},"            }\n",[37,2239,2240,2242],{"class":39,"line":879},[37,2241,1186],{"class":50},[37,2243,1497],{"class":68},[37,2245,2246],{"class":39,"line":892},[37,2247,1222],{"class":68},[37,2249,2250],{"class":39,"line":904},[37,2251,528],{"class":68},[37,2253,2254,2257,2259,2262,2265,2267,2270,2273],{"class":39,"line":909},[37,2255,2256],{"class":64},"    addHandler",[37,2258,69],{"class":68},[37,2260,2261],{"class":408},"handler",[37,2263,2264],{"class":68},") { ",[37,2266,509],{"class":54},[37,2268,2269],{"class":68},".handlers.",[37,2271,2272],{"class":64},"push",[37,2274,2275],{"class":68},"(handler); }\n",[37,2277,2278],{"class":39,"line":922},[37,2279,361],{"class":68},[15,2281,2283],{"id":2282},"tips-tricks","💡 Tips & Tricks",[25,2285,2286],{"language":27},[29,2287,2289],{"className":31,"code":2288,"language":27,"meta":33,"style":33},"\u002F\u002F ── Error.cause for error chains (ES2022) ──\ntry {\n    await fetch(url);\n} catch (networkError) {\n    throw new Error(\"API call failed\", { cause: networkError });\n    \u002F\u002F The original error is preserved in .cause — full debug trail\n}\n\n\u002F\u002F ── Error.captureStackTrace (V8\u002FNode) for clean stack traces ──\nclass MyError extends Error {\n    constructor(message) {\n        super(message);\n        Error.captureStackTrace(this, MyError);  \u002F\u002F skips the MyError constructor frame\n    }\n}\n\n\u002F\u002F ── `throw` can throw anything (not just Error objects) ──\n\u002F\u002F throw \"string error\";   \u002F\u002F works but bad practice (no stack trace)\n\u002F\u002F throw { code: 42 };     \u002F\u002F works but bad practice\n\u002F\u002F ALWAYS throw an Error (or subclass) — it has a stack trace.\n\u002F\u002F If you catch non-Error throws: try { ... } catch (e) { if (e instanceof Error) ... }\n\n\u002F\u002F ── AggregateError (ES2021) — multiple errors in one ──\nconst errors = [\n    new Error(\"error 1\"),\n    new Error(\"error 2\"),\n];\nthrow new AggregateError(errors, \"multiple failures\");\n\u002F\u002F catch: err.errors → [Error(\"error 1\"), Error(\"error 2\")]\n\n\u002F\u002F ── Structured error for API responses ──\nfunction toApiError(error) {\n    return {\n        error: {\n            code: error.code ?? \"UNKNOWN\",\n            message: error.message ?? \"An error occurred\",\n            field: error.field,\n            ...(process.env.NODE_ENV === \"development\" && { stack: error.stack }),\n        },\n    };\n}\n",[20,2290,2291,2296,2302,2311,2320,2336,2341,2345,2349,2354,2367,2377,2384,2400,2404,2408,2412,2417,2425,2433,2438,2443,2447,2452,2464,2479,2492,2497,2515,2520,2524,2529,2542,2548,2553,2566,2578,2583,2606,2611,2616],{"__ignoreMap":33},[37,2292,2293],{"class":39,"line":40},[37,2294,2295],{"class":43},"\u002F\u002F ── Error.cause for error chains (ES2022) ──\n",[37,2297,2298,2300],{"class":39,"line":47},[37,2299,160],{"class":50},[37,2301,305],{"class":68},[37,2303,2304,2307,2309],{"class":39,"line":79},[37,2305,2306],{"class":50},"    await",[37,2308,1164],{"class":64},[37,2310,1167],{"class":68},[37,2312,2313,2315,2317],{"class":39,"line":94},[37,2314,326],{"class":68},[37,2316,166],{"class":50},[37,2318,2319],{"class":68}," (networkError) {\n",[37,2321,2322,2324,2326,2328,2330,2333],{"class":39,"line":107},[37,2323,337],{"class":50},[37,2325,61],{"class":50},[37,2327,65],{"class":64},[37,2329,69],{"class":68},[37,2331,2332],{"class":72},"\"API call failed\"",[37,2334,2335],{"class":68},", { cause: networkError });\n",[37,2337,2338],{"class":39,"line":120},[37,2339,2340],{"class":43},"    \u002F\u002F The original error is preserved in .cause — full debug trail\n",[37,2342,2343],{"class":39,"line":126},[37,2344,361],{"class":68},[37,2346,2347],{"class":39,"line":132},[37,2348,142],{"emptyLinePlaceholder":141},[37,2350,2351],{"class":39,"line":138},[37,2352,2353],{"class":43},"\u002F\u002F ── Error.captureStackTrace (V8\u002FNode) for clean stack traces ──\n",[37,2355,2356,2358,2361,2363,2365],{"class":39,"line":145},[37,2357,388],{"class":50},[37,2359,2360],{"class":64}," MyError",[37,2362,394],{"class":50},[37,2364,65],{"class":64},[37,2366,305],{"class":68},[37,2368,2369,2371,2373,2375],{"class":39,"line":151},[37,2370,403],{"class":50},[37,2372,69],{"class":68},[37,2374,409],{"class":408},[37,2376,648],{"class":68},[37,2378,2379,2381],{"class":39,"line":157},[37,2380,438],{"class":54},[37,2382,2383],{"class":68},"(message);\n",[37,2385,2386,2388,2390,2392,2394,2397],{"class":39,"line":189},[37,2387,500],{"class":68},[37,2389,503],{"class":64},[37,2391,69],{"class":68},[37,2393,509],{"class":54},[37,2395,2396],{"class":68},", MyError);  ",[37,2398,2399],{"class":43},"\u002F\u002F skips the MyError constructor frame\n",[37,2401,2402],{"class":39,"line":228},[37,2403,528],{"class":68},[37,2405,2406],{"class":39,"line":264},[37,2407,361],{"class":68},[37,2409,2410],{"class":39,"line":289},[37,2411,142],{"emptyLinePlaceholder":141},[37,2413,2414],{"class":39,"line":294},[37,2415,2416],{"class":43},"\u002F\u002F ── `throw` can throw anything (not just Error objects) ──\n",[37,2418,2419,2422],{"class":39,"line":300},[37,2420,2421],{"class":43},"\u002F\u002F throw \"string error\";",[37,2423,2424],{"class":43},"   \u002F\u002F works but bad practice (no stack trace)\n",[37,2426,2427,2430],{"class":39,"line":308},[37,2428,2429],{"class":43},"\u002F\u002F throw { code: 42 };",[37,2431,2432],{"class":43},"     \u002F\u002F works but bad practice\n",[37,2434,2435],{"class":39,"line":323},[37,2436,2437],{"class":43},"\u002F\u002F ALWAYS throw an Error (or subclass) — it has a stack trace.\n",[37,2439,2440],{"class":39,"line":334},[37,2441,2442],{"class":43},"\u002F\u002F If you catch non-Error throws: try { ... } catch (e) { if (e instanceof Error) ... }\n",[37,2444,2445],{"class":39,"line":352},[37,2446,142],{"emptyLinePlaceholder":141},[37,2448,2449],{"class":39,"line":358},[37,2450,2451],{"class":43},"\u002F\u002F ── AggregateError (ES2021) — multiple errors in one ──\n",[37,2453,2454,2456,2459,2461],{"class":39,"line":364},[37,2455,51],{"class":50},[37,2457,2458],{"class":54}," errors",[37,2460,58],{"class":50},[37,2462,2463],{"class":68}," [\n",[37,2465,2466,2469,2471,2473,2476],{"class":39,"line":699},[37,2467,2468],{"class":50},"    new",[37,2470,65],{"class":64},[37,2472,69],{"class":68},[37,2474,2475],{"class":72},"\"error 1\"",[37,2477,2478],{"class":68},"),\n",[37,2480,2481,2483,2485,2487,2490],{"class":39,"line":712},[37,2482,2468],{"class":50},[37,2484,65],{"class":64},[37,2486,69],{"class":68},[37,2488,2489],{"class":72},"\"error 2\"",[37,2491,2478],{"class":68},[37,2493,2494],{"class":39,"line":725},[37,2495,2496],{"class":68},"];\n",[37,2498,2499,2502,2504,2507,2510,2513],{"class":39,"line":730},[37,2500,2501],{"class":50},"throw",[37,2503,61],{"class":50},[37,2505,2506],{"class":64}," AggregateError",[37,2508,2509],{"class":68},"(errors, ",[37,2511,2512],{"class":72},"\"multiple failures\"",[37,2514,76],{"class":68},[37,2516,2517],{"class":39,"line":735},[37,2518,2519],{"class":43},"\u002F\u002F catch: err.errors → [Error(\"error 1\"), Error(\"error 2\")]\n",[37,2521,2522],{"class":39,"line":740},[37,2523,142],{"emptyLinePlaceholder":141},[37,2525,2526],{"class":39,"line":754},[37,2527,2528],{"class":43},"\u002F\u002F ── Structured error for API responses ──\n",[37,2530,2531,2533,2536,2538,2540],{"class":39,"line":778},[37,2532,832],{"class":50},[37,2534,2535],{"class":64}," toApiError",[37,2537,69],{"class":68},[37,2539,840],{"class":408},[37,2541,648],{"class":68},[37,2543,2544,2546],{"class":39,"line":795},[37,2545,995],{"class":50},[37,2547,305],{"class":68},[37,2549,2550],{"class":39,"line":808},[37,2551,2552],{"class":68},"        error: {\n",[37,2554,2555,2558,2561,2564],{"class":39,"line":813},[37,2556,2557],{"class":68},"            code: error.code ",[37,2559,2560],{"class":50},"??",[37,2562,2563],{"class":72}," \"UNKNOWN\"",[37,2565,681],{"class":68},[37,2567,2568,2571,2573,2576],{"class":39,"line":818},[37,2569,2570],{"class":68},"            message: error.message ",[37,2572,2560],{"class":50},[37,2574,2575],{"class":72}," \"An error occurred\"",[37,2577,681],{"class":68},[37,2579,2580],{"class":39,"line":823},[37,2581,2582],{"class":68},"            field: error.field,\n",[37,2584,2585,2588,2591,2594,2597,2600,2603],{"class":39,"line":829},[37,2586,2587],{"class":50},"            ...",[37,2589,2590],{"class":68},"(process.env.",[37,2592,2593],{"class":54},"NODE_ENV",[37,2595,2596],{"class":50}," ===",[37,2598,2599],{"class":72}," \"development\"",[37,2601,2602],{"class":50}," &&",[37,2604,2605],{"class":68}," { stack: error.stack }),\n",[37,2607,2608],{"class":39,"line":845},[37,2609,2610],{"class":68},"        },\n",[37,2612,2613],{"class":39,"line":860},[37,2614,2615],{"class":68},"    };\n",[37,2617,2618],{"class":39,"line":874},[37,2619,361],{"class":68},[15,2621,2623],{"id":2622},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[25,2625,2626],{"language":27},[29,2627,2629],{"className":31,"code":2628,"language":27,"meta":33,"style":33},"\u002F\u002F ── `throw` can throw any value (not just Error) ──\n\u002F\u002F throw \"string\";  \u002F\u002F catch(e) → e is \"string\" (no .stack, no .message)\n\u002F\u002F Always throw new Error() or a subclass — for stack traces and consistency.\n\u002F\u002F In catch: if (e instanceof Error) ... else \u002F\u002F handle non-Error throws\n\n\u002F\u002F ── `finally` runs even after return (and can override the return value) ──\nfunction f() {\n    try { return \"try\"; }\n    finally { return \"finally\"; }  \u002F\u002F overrides \"try\" — returns \"finally\"\n}\n\u002F\u002F Don't return from finally — it silently swallows errors and return values.\n\n\u002F\u002F ── Async errors don't propagate to the caller's try\u002Fcatch without await ──\nasync function f() { throw new Error(\"async error\"); }\ntry {\n    f();  \u002F\u002F doesn't throw — returns a rejected Promise (not awaited)\n} catch (e) {\n    console.log(\"caught\");  \u002F\u002F NOT reached — the rejection is unhandled\n}\n\u002F\u002F Fix: await f() or f().catch(...)\n\n\u002F\u002F ── `catch` without a parameter (ES2019) ──\ntry { JSON.parse(data) } catch { console.log(\"parse failed\") }  \u002F\u002F no (e) needed\n\n\u002F\u002F ── Error.stack is non-standard (format varies by engine) ──\n\u002F\u002F V8 (Chrome\u002FNode): multi-line string with function names and positions\n\u002F\u002F SpiderMonkey (Firefox): different format\n\u002F\u002F Don't parse .stack programmatically — use Error.prepareStackTrace (V8) or source maps.\n\n\u002F\u002F ── `Error.captureStackTrace` is V8-only (not in Firefox\u002FSafari) ──\n\u002F\u002F Use optional chaining: Error.captureStackTrace?.(this, constructor)\n\n\u002F\u002F ── `instanceof Error` is false for non-Error throws ──\ntry { throw \"string\" } catch (e) { console.log(e instanceof Error); }  \u002F\u002F false\n",[20,2630,2631,2636,2644,2649,2657,2661,2666,2675,2689,2707,2711,2716,2720,2725,2750,2756,2766,2774,2790,2794,2799,2803,2808,2842,2846,2851,2856,2861,2866,2870,2875,2880,2884,2889],{"__ignoreMap":33},[37,2632,2633],{"class":39,"line":40},[37,2634,2635],{"class":43},"\u002F\u002F ── `throw` can throw any value (not just Error) ──\n",[37,2637,2638,2641],{"class":39,"line":47},[37,2639,2640],{"class":43},"\u002F\u002F throw \"string\";",[37,2642,2643],{"class":43},"  \u002F\u002F catch(e) → e is \"string\" (no .stack, no .message)\n",[37,2645,2646],{"class":39,"line":79},[37,2647,2648],{"class":43},"\u002F\u002F Always throw new Error() or a subclass — for stack traces and consistency.\n",[37,2650,2651,2654],{"class":39,"line":94},[37,2652,2653],{"class":43},"\u002F\u002F In catch: if (e instanceof Error) ... else",[37,2655,2656],{"class":43}," \u002F\u002F handle non-Error throws\n",[37,2658,2659],{"class":39,"line":107},[37,2660,142],{"emptyLinePlaceholder":141},[37,2662,2663],{"class":39,"line":120},[37,2664,2665],{"class":43},"\u002F\u002F ── `finally` runs even after return (and can override the return value) ──\n",[37,2667,2668,2670,2673],{"class":39,"line":126},[37,2669,832],{"class":50},[37,2671,2672],{"class":64}," f",[37,2674,1394],{"class":68},[37,2676,2677,2679,2681,2683,2686],{"class":39,"line":132},[37,2678,1146],{"class":50},[37,2680,233],{"class":68},[37,2682,2223],{"class":50},[37,2684,2685],{"class":72}," \"try\"",[37,2687,2688],{"class":68},"; }\n",[37,2690,2691,2694,2696,2698,2701,2704],{"class":39,"line":138},[37,2692,2693],{"class":50},"    finally",[37,2695,233],{"class":68},[37,2697,2223],{"class":50},[37,2699,2700],{"class":72}," \"finally\"",[37,2702,2703],{"class":68},"; }  ",[37,2705,2706],{"class":43},"\u002F\u002F overrides \"try\" — returns \"finally\"\n",[37,2708,2709],{"class":39,"line":145},[37,2710,361],{"class":68},[37,2712,2713],{"class":39,"line":151},[37,2714,2715],{"class":43},"\u002F\u002F Don't return from finally — it silently swallows errors and return values.\n",[37,2717,2718],{"class":39,"line":157},[37,2719,142],{"emptyLinePlaceholder":141},[37,2721,2722],{"class":39,"line":189},[37,2723,2724],{"class":43},"\u002F\u002F ── Async errors don't propagate to the caller's try\u002Fcatch without await ──\n",[37,2726,2727,2729,2731,2733,2736,2738,2740,2742,2744,2747],{"class":39,"line":228},[37,2728,1128],{"class":50},[37,2730,1131],{"class":50},[37,2732,2672],{"class":64},[37,2734,2735],{"class":68},"() { ",[37,2737,2501],{"class":50},[37,2739,61],{"class":50},[37,2741,65],{"class":64},[37,2743,69],{"class":68},[37,2745,2746],{"class":72},"\"async error\"",[37,2748,2749],{"class":68},"); }\n",[37,2751,2752,2754],{"class":39,"line":264},[37,2753,160],{"class":50},[37,2755,305],{"class":68},[37,2757,2758,2761,2763],{"class":39,"line":289},[37,2759,2760],{"class":64},"    f",[37,2762,1675],{"class":68},[37,2764,2765],{"class":43},"\u002F\u002F doesn't throw — returns a rejected Promise (not awaited)\n",[37,2767,2768,2770,2772],{"class":39,"line":294},[37,2769,326],{"class":68},[37,2771,166],{"class":50},[37,2773,1728],{"class":68},[37,2775,2776,2778,2780,2782,2785,2787],{"class":39,"line":300},[37,2777,979],{"class":68},[37,2779,85],{"class":64},[37,2781,69],{"class":68},[37,2783,2784],{"class":72},"\"caught\"",[37,2786,520],{"class":68},[37,2788,2789],{"class":43},"\u002F\u002F NOT reached — the rejection is unhandled\n",[37,2791,2792],{"class":39,"line":308},[37,2793,361],{"class":68},[37,2795,2796],{"class":39,"line":323},[37,2797,2798],{"class":43},"\u002F\u002F Fix: await f() or f().catch(...)\n",[37,2800,2801],{"class":39,"line":334},[37,2802,142],{"emptyLinePlaceholder":141},[37,2804,2805],{"class":39,"line":352},[37,2806,2807],{"class":43},"\u002F\u002F ── `catch` without a parameter (ES2019) ──\n",[37,2809,2810,2812,2814,2817,2819,2821,2824,2826,2829,2831,2833,2836,2839],{"class":39,"line":358},[37,2811,160],{"class":50},[37,2813,233],{"class":68},[37,2815,2816],{"class":54},"JSON",[37,2818,314],{"class":68},[37,2820,317],{"class":64},[37,2822,2823],{"class":68},"(data) } ",[37,2825,166],{"class":50},[37,2827,2828],{"class":68}," { console.",[37,2830,85],{"class":64},[37,2832,69],{"class":68},[37,2834,2835],{"class":72},"\"parse failed\"",[37,2837,2838],{"class":68},") }  ",[37,2840,2841],{"class":43},"\u002F\u002F no (e) needed\n",[37,2843,2844],{"class":39,"line":364},[37,2845,142],{"emptyLinePlaceholder":141},[37,2847,2848],{"class":39,"line":699},[37,2849,2850],{"class":43},"\u002F\u002F ── Error.stack is non-standard (format varies by engine) ──\n",[37,2852,2853],{"class":39,"line":712},[37,2854,2855],{"class":43},"\u002F\u002F V8 (Chrome\u002FNode): multi-line string with function names and positions\n",[37,2857,2858],{"class":39,"line":725},[37,2859,2860],{"class":43},"\u002F\u002F SpiderMonkey (Firefox): different format\n",[37,2862,2863],{"class":39,"line":730},[37,2864,2865],{"class":43},"\u002F\u002F Don't parse .stack programmatically — use Error.prepareStackTrace (V8) or source maps.\n",[37,2867,2868],{"class":39,"line":735},[37,2869,142],{"emptyLinePlaceholder":141},[37,2871,2872],{"class":39,"line":740},[37,2873,2874],{"class":43},"\u002F\u002F ── `Error.captureStackTrace` is V8-only (not in Firefox\u002FSafari) ──\n",[37,2876,2877],{"class":39,"line":754},[37,2878,2879],{"class":43},"\u002F\u002F Use optional chaining: Error.captureStackTrace?.(this, constructor)\n",[37,2881,2882],{"class":39,"line":778},[37,2883,142],{"emptyLinePlaceholder":141},[37,2885,2886],{"class":39,"line":795},[37,2887,2888],{"class":43},"\u002F\u002F ── `instanceof Error` is false for non-Error throws ──\n",[37,2890,2891,2893,2895,2897,2900,2902,2904,2906,2908,2910,2912,2914,2916],{"class":39,"line":808},[37,2892,160],{"class":50},[37,2894,233],{"class":68},[37,2896,2501],{"class":50},[37,2898,2899],{"class":72}," \"string\"",[37,2901,208],{"class":68},[37,2903,166],{"class":50},[37,2905,169],{"class":68},[37,2907,85],{"class":64},[37,2909,174],{"class":68},[37,2911,177],{"class":50},[37,2913,65],{"class":64},[37,2915,183],{"class":68},[37,2917,2918],{"class":43},"\u002F\u002F false\n",[15,2920,2922],{"id":2921},"quick-quiz","🧠 Quick Quiz",[2924,2925,2926],"p",{},"What's the output?",[25,2928,2929],{"language":27},[29,2930,2932],{"className":31,"code":2931,"language":27,"meta":33,"style":33},"async function test() {\n    try {\n        throw new Error(\"A\");\n    } catch (e) {\n        console.log(\"B\", e.message);\n        throw new Error(\"C\");\n    } finally {\n        console.log(\"D\");\n    }\n}\ntest().catch(e => console.log(\"E\", e.message));\n",[20,2933,2934,2945,2951,2966,2974,2988,3003,3011,3024,3028,3032],{"__ignoreMap":33},[37,2935,2936,2938,2940,2943],{"class":39,"line":40},[37,2937,1128],{"class":50},[37,2939,1131],{"class":50},[37,2941,2942],{"class":64}," test",[37,2944,1394],{"class":68},[37,2946,2947,2949],{"class":39,"line":47},[37,2948,1146],{"class":50},[37,2950,305],{"class":68},[37,2952,2953,2955,2957,2959,2961,2964],{"class":39,"line":79},[37,2954,1294],{"class":50},[37,2956,61],{"class":50},[37,2958,65],{"class":64},[37,2960,69],{"class":68},[37,2962,2963],{"class":72},"\"A\"",[37,2965,76],{"class":68},[37,2967,2968,2970,2972],{"class":39,"line":94},[37,2969,1242],{"class":68},[37,2971,166],{"class":50},[37,2973,1728],{"class":68},[37,2975,2976,2978,2980,2982,2985],{"class":39,"line":107},[37,2977,925],{"class":68},[37,2979,85],{"class":64},[37,2981,69],{"class":68},[37,2983,2984],{"class":72},"\"B\"",[37,2986,2987],{"class":68},", e.message);\n",[37,2989,2990,2992,2994,2996,2998,3001],{"class":39,"line":120},[37,2991,1294],{"class":50},[37,2993,61],{"class":50},[37,2995,65],{"class":64},[37,2997,69],{"class":68},[37,2999,3000],{"class":72},"\"C\"",[37,3002,76],{"class":68},[37,3004,3005,3007,3009],{"class":39,"line":126},[37,3006,1242],{"class":68},[37,3008,1660],{"class":50},[37,3010,305],{"class":68},[37,3012,3013,3015,3017,3019,3022],{"class":39,"line":132},[37,3014,925],{"class":68},[37,3016,85],{"class":64},[37,3018,69],{"class":68},[37,3020,3021],{"class":72},"\"D\"",[37,3023,76],{"class":68},[37,3025,3026],{"class":39,"line":138},[37,3027,528],{"class":68},[37,3029,3030],{"class":39,"line":145},[37,3031,361],{"class":68},[37,3033,3034,3037,3040,3042,3044,3047,3049,3051,3053,3055,3058],{"class":39,"line":151},[37,3035,3036],{"class":64},"test",[37,3038,3039],{"class":68},"().",[37,3041,166],{"class":64},[37,3043,69],{"class":68},[37,3045,3046],{"class":408},"e",[37,3048,1341],{"class":50},[37,3050,1344],{"class":68},[37,3052,85],{"class":64},[37,3054,69],{"class":68},[37,3056,3057],{"class":72},"\"E\"",[37,3059,3060],{"class":68},", e.message));\n",[3062,3063,3064,3068,3076,3128],"details",{},[3065,3066,3067],"summary",{},"Answer",[29,3069,3074],{"className":3070,"code":3072,"language":3073},[3071],"language-text","B A\nD\nE C\n","text",[20,3075,3072],{"__ignoreMap":33},[3077,3078,3079,3092,3103,3109,3116,3119],"ol",{},[3080,3081,3082,3085,3086,3089,3090,314],"li",{},[20,3083,3084],{},"test()"," is called. Inside: ",[20,3087,3088],{},"throw new Error(\"A\")"," → caught by ",[20,3091,166],{},[3080,3093,3094,3097,3098,3100,3101,314],{},[20,3095,3096],{},"B A"," — catch logs ",[20,3099,2984],{}," and the error message ",[20,3102,2963],{},[3080,3104,3105,3108],{},[20,3106,3107],{},"throw new Error(\"C\")"," — re-throws a new error.",[3080,3110,3111,3113,3114,314],{},[20,3112,1660],{}," runs (always): logs ",[20,3115,3021],{},[3080,3117,3118],{},"The function returns a rejected Promise (Error(\"C\") was thrown).",[3080,3120,3121,3124,3125,314],{},[20,3122,3123],{},".catch(e => ...)"," catches the rejection: logs ",[20,3126,3127],{},"\"E C\"",[2924,3129,3130,3134,3135,3137,3138,3140,3141,3143,3144,3140,3146,3148,3149,3152],{},[3131,3132,3133],"strong",{},"The lesson",": ",[20,3136,1660],{}," always runs (even after a ",[20,3139,2501],{}," in ",[20,3142,166],{},"). The ",[20,3145,3107],{},[20,3147,166],{}," propagates as a rejected Promise, caught by ",[20,3150,3151],{},".catch()"," in the caller.",[3154,3155,3156],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":33,"searchDepth":47,"depth":47,"links":3158},[3159,3161,3162,3163,3164,3165,3166,3167],{"id":17,"depth":47,"text":3160},"The Error Object Internals",{"id":370,"depth":47,"text":371},{"id":1110,"depth":47,"text":1111},{"id":1689,"depth":47,"text":1690},{"id":1885,"depth":47,"text":1886},{"id":2282,"depth":47,"text":2283},{"id":2622,"depth":47,"text":2623},{"id":2921,"depth":47,"text":2922},"Deep-dive into JavaScript error handling: try\u002Fcatch\u002Ffinally semantics, the Error object and stack trace internals, custom error hierarchies, async error propagation, and global error handlers. Code-first reference for senior engineers.","md",{},"\u002Fjs\u002F18-error-handling",{"title":5,"description":3168},"js\u002F18-error-handling","yyISQDa4oKGC2HsT0NF589oFH1p--2y3n5XWuXI2vp8",1789924649392]