[{"data":1,"prerenderedAt":657},["ShallowReactive",2],{"navigation_docs":3,"-guide-debugging":93,"-guide-debugging-surround":652},[4,71],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":70},"Guide","i-lucide-book-open","\u002Fguide","1.guide",[10,14,18,22,26,30,34,38,42,46,50,54,58,62,66],{"title":11,"path":12,"stem":13},"Getting started","\u002Fguide\u002Fgetting-started","1.guide\u002F01.getting-started",{"title":15,"path":16,"stem":17},"Adoption paths","\u002Fguide\u002Fadoption","1.guide\u002F02.adoption",{"title":19,"path":20,"stem":21},"Routes and typed $fetch","\u002Fguide\u002Froutes","1.guide\u002F02.routes",{"title":23,"path":24,"stem":25},"Kyo handlers","\u002Fguide\u002Fkyo","1.guide\u002F03.kyo",{"title":27,"path":28,"stem":29},"ZIO handlers","\u002Fguide\u002Fzio","1.guide\u002F04.zio",{"title":31,"path":32,"stem":33},"Configuration and secrets","\u002Fguide\u002Fconfiguration","1.guide\u002F05.configuration",{"title":35,"path":36,"stem":37},"Application and request lifetimes","\u002Fguide\u002Flifetimes","1.guide\u002F06.lifetimes",{"title":39,"path":40,"stem":41},"Schemas","\u002Fguide\u002Fschema","1.guide\u002F07.schema",{"title":43,"path":44,"stem":45},"PostgreSQL","\u002Fguide\u002Fdatabase","1.guide\u002F08.database",{"title":47,"path":48,"stem":49},"Streaming and cancellation","\u002Fguide\u002Fstreaming","1.guide\u002F09.streaming",{"title":51,"path":52,"stem":53},"Testing","\u002Fguide\u002Ftesting","1.guide\u002F10.testing",{"title":55,"path":56,"stem":57},"Nitro storage and NuxtHub KV","\u002Fguide\u002Fstorage","1.guide\u002F11.storage",{"title":59,"path":60,"stem":61},"Debug Scala handlers","\u002Fguide\u002Fdebugging","1.guide\u002F12.debugging",{"title":63,"path":64,"stem":65},"npm build tooling","\u002Fguide\u002Fnpm-tooling","1.guide\u002F13.npm-tooling",{"title":67,"path":68,"stem":69},"Set up h34s with a coding assistant","\u002Fguide\u002Fagent-setup","1.guide\u002F14.agent-setup",false,{"title":72,"icon":73,"path":74,"stem":75,"children":76,"page":70},"Reference","i-lucide-library","\u002Freference","2.reference",[77,81,85,89],{"title":78,"path":79,"stem":80},"Architecture","\u002Freference\u002Farchitecture","2.reference\u002F1.architecture",{"title":82,"path":83,"stem":84},"Releases","\u002Freference\u002Freleases","2.reference\u002F2.releases",{"title":86,"path":87,"stem":88},"Compatibility","\u002Freference\u002Fcompatibility","2.reference\u002F3.compatibility",{"title":90,"path":91,"stem":92},"Migration guide","\u002Freference\u002Fmigration","2.reference\u002F4.migration",{"id":94,"title":59,"body":95,"description":645,"extension":646,"links":647,"meta":648,"navigation":649,"path":60,"seo":650,"stem":61,"__hash__":651},"docs\u002F1.guide\u002F12.debugging.md",{"type":96,"value":97,"toc":637},"minimark",[98,102,110,115,127,165,168,238,259,279,286,290,302,373,397,403,415,429,433,439,481,484,521,535,539,542,553,556,560,571,575,584,598,633],[99,100,101],"p",{},"h34s keeps production errors opaque and shows full diagnostics while you develop. You do not add a debug flag to your handlers: the h34s Nitro plugin decides, and requests can never change its decision.",[99,103,104,105,109],{},"Install the ",[106,107,108],"a",{"href":64},"npm Nuxt module"," first. It registers the plugin, the development loader and the source-map integration.",[111,112,114],"h2",{"id":113},"what-clients-see","What clients see",[99,116,117,118,122,123,126],{},"An unexpected failure is any ",[119,120,121],"code",{},"Throwable"," that is not an approved ",[119,124,125],{},"SafeError",": a thrown exception, a panic, a converter defect, a non-safe ZIO failure, or a ZIO defect. With the default options, the client gets:",[128,129,134],"pre",{"className":130,"code":131,"language":132,"meta":133,"style":133},"language-json shiki shiki-themes github-light github-light github-dark","{ \"errors\": [{ \"message\": \"Internal server error\" }] }\n","json","",[119,135,136],{"__ignoreMap":133},[137,138,141,145,149,152,155,158,162],"span",{"class":139,"line":140},"line",1,[137,142,144],{"class":143},"sxrX7","{ ",[137,146,148],{"class":147},"sBjJW","\"errors\"",[137,150,151],{"class":143},": [{ ",[137,153,154],{"class":147},"\"message\"",[137,156,157],{"class":143},": ",[137,159,161],{"class":160},"sIIMD","\"Internal server error\"",[137,163,164],{"class":143}," }] }\n",[99,166,167],{},"with status 500. When diagnostics are on, the same entry carries the cause:",[128,169,171],{"className":130,"code":170,"language":132,"meta":133,"style":133},"{\n  \"errors\": [{\n    \"message\": \"Internal server error\",\n    \"debug\": { \"cause\": \"java.lang.IllegalStateException: ...\\n\\tat ...\" }\n  }]\n}\n",[119,172,173,178,187,200,226,232],{"__ignoreMap":133},[137,174,175],{"class":139,"line":140},[137,176,177],{"class":143},"{\n",[137,179,181,184],{"class":139,"line":180},2,[137,182,183],{"class":147},"  \"errors\"",[137,185,186],{"class":143},": [{\n",[137,188,190,193,195,197],{"class":139,"line":189},3,[137,191,192],{"class":147},"    \"message\"",[137,194,157],{"class":143},[137,196,161],{"class":160},[137,198,199],{"class":143},",\n",[137,201,203,206,209,212,214,217,220,223],{"class":139,"line":202},4,[137,204,205],{"class":147},"    \"debug\"",[137,207,208],{"class":143},": { ",[137,210,211],{"class":147},"\"cause\"",[137,213,157],{"class":143},[137,215,216],{"class":160},"\"java.lang.IllegalStateException: ...",[137,218,219],{"class":147},"\\n\\t",[137,221,222],{"class":160},"at ...\"",[137,224,225],{"class":143}," }\n",[137,227,229],{"class":139,"line":228},5,[137,230,231],{"class":143},"  }]\n",[137,233,235],{"class":139,"line":234},6,[137,236,237],{"class":143},"}\n",[239,240,241,249],"ul",{},[242,243,244,245,248],"li",{},"Kyo handlers: ",[119,246,247],{},"cause"," is the exception's class, message, cause chain and stack text.",[242,250,251,252,254,255,258],{},"ZIO handlers: ",[119,253,247],{}," is ZIO's full ",[119,256,257],{},"Cause.prettyPrint",", with ZIO traces and Scala source lines.",[99,260,261,263,264,267,268,271,272,275,276,278],{},[119,262,125],{}," entries never carry ",[119,265,266],{},"debug",". Their status and messages are the same in every mode. With ",[119,269,270],{},"ErrorEnvelope.SingleOrList",", the one entry is under ",[119,273,274],{},"\"error\""," instead of ",[119,277,148],{},".",[99,280,281,282,285],{},"The server logs every unexpected failure as ",[119,283,284],{},"Unhandled h34s handler failure"," with the same details, in every mode.",[111,287,289],{"id":288},"when-diagnostics-are-on","When diagnostics are on",[99,291,292,293,297,298,301],{},"Diagnostics are on when the request's development flag ",[294,295,296],"strong",{},"or"," debug flag is the boolean ",[119,299,300],{},"true",":",[303,304,305,321],"table",{},[306,307,308],"thead",{},[309,310,311,315,318],"tr",{},[312,313,314],"th",{},"Flag",[312,316,317],{},"Set by",[312,319,320],{},"When",[322,323,324,347],"tbody",{},[309,325,326,332,338],{},[327,328,329],"td",{},[119,330,331],{},"development",[327,333,334,335],{},"The plugin, from Nitro's ",[119,336,337],{},"import.meta.dev",[327,339,340,343,344],{},[119,341,342],{},"nuxt dev",". A production build compiles it to ",[119,345,346],{},"false",[309,348,349,353,360],{},[327,350,351],{},[119,352,266],{},[327,354,355,356,359],{},"The plugin, from ",[119,357,358],{},"runtimeConfig.h34s.debug",", read once at startup",[327,361,362,365,366,369,370],{},[119,363,364],{},"NUXT_H34S_DEBUG=true"," at runtime, or ",[119,367,368],{},"runtimeConfig: { h34s: { debug: true } }"," in ",[119,371,372],{},"nuxt.config.ts",[99,374,375,376,379,380,383,384,386,387,389,390,392,393,396],{},"The Nuxt module declares ",[119,377,378],{},"runtimeConfig.h34s.debug: false",", which is why ",[119,381,382],{},"NUXT_H34S_DEBUG"," can override it. If your ",[119,385,372],{}," already sets ",[119,388,358],{},", your value wins. Nuxt's own ",[119,391,266],{}," option does not turn on h34s debug mode: Nuxt resolves it to an object, and the ",[119,394,395],{},"DEBUG"," environment variable of a build machine can set it. Restart the server after you change the variable.",[99,398,399,400,402],{},"Without the plugin, both flags are ",[119,401,346],{}," and every failure is opaque.",[99,404,405,408,409,411,412,414],{},[294,406,407],{},"Keep debug mode off in production."," Diagnostics send exception messages and stack text to anyone who can trigger a failure. Libraries can put connection details, SQL text or file paths in exception messages. Use debug mode only on a server that only you can reach, and turn it off again. If you turned it on by mistake, unset ",[119,410,382],{}," (or set it to ",[119,413,346],{},") and restart.",[99,416,417,418,421,422,425,426,428],{},"These flags are tested with a stubbed Nitro runtime (",[119,419,420],{},"packages\u002Fnuxt\u002Ftest",") and with fake plugin records in the Scala suites. In a production build of the demo (macOS x86_64), an unexpected failure was opaque without the variable and carried ",[119,423,424],{},"debug.cause"," with ",[119,427,364],{},"; the database password did not appear in either response.",[111,430,432],{"id":431},"map-javascript-back-to-scala","Map JavaScript back to Scala",[99,434,435,436,438],{},"During ",[119,437,342],{},", Node loads the linked Scala.js modules directly and reads their source maps:",[440,441,442,463,466],"ol",{},[242,443,444,447,448,451,452,455,456,459,460,278],{},[119,445,446],{},"fastLinkJS"," writes JavaScript and ",[119,449,450],{},".js.map"," files to the output directories in your ",[119,453,454],{},"h34s.config.mjs",". The demo uses ",[119,457,458],{},"examples\u002Fnuxt\u002Fserver\u002F.scala"," and ",[119,461,462],{},"examples\u002Fnuxt\u002Fserver\u002F.scala-kyo",[242,464,465],{},"The module's development loader keeps those outputs out of Nitro's development bundle and imports them as native files. Nitro watches the directories and replaces its worker after you relink.",[242,467,468,469,472,473,476,477,480],{},"Start Nuxt with ",[119,470,471],{},"node --enable-source-maps",", as in the ",[119,474,475],{},"dev"," script of ",[106,478,479],{"href":64},"npm tooling",". Node then maps stack frames to Scala files and lines.",[99,482,483],{},"Enable source maps in your Scala.js build:",[128,485,489],{"className":486,"code":487,"language":488,"meta":133,"style":133},"language-scala shiki shiki-themes github-light github-light github-dark","Compile \u002F fastLinkJS \u002F scalaJSLinkerConfig ~= (_.withSourceMap(true)),\n","scala",[119,490,491],{"__ignoreMap":133},[137,492,493,497,501,504,507,510,513,516,518],{"class":139,"line":140},[137,494,496],{"class":495},"snPdu","Compile",[137,498,500],{"class":499},"s8jYJ"," \u002F",[137,502,503],{"class":143}," fastLinkJS ",[137,505,506],{"class":499},"\u002F",[137,508,509],{"class":143}," scalaJSLinkerConfig ",[137,511,512],{"class":499},"~=",[137,514,515],{"class":143}," (_.withSourceMap(",[137,517,300],{"class":147},[137,519,520],{"class":143},")),\n",[99,522,523,524,527,528,530,531,534],{},"Keep each ",[119,525,526],{},".js"," file next to its ",[119,529,450],{},". The package also has a source-map helper that composes Scala.js maps through Nitro\u002FRollup. It embeds your project's Scala sources, from the application root and from the config's ",[119,532,533],{},"sbtRoot",", and never downloads dependency sources. ",[111,536,538],{"id":537},"attach-a-debugger","Attach a debugger",[99,540,541],{},"Start Nuxt with the inspector from your application root:",[128,543,547],{"className":544,"code":545,"language":546,"meta":133,"style":133},"language-sh shiki shiki-themes github-light github-light github-dark","pnpm dev --inspect\n","sh",[119,548,549],{"__ignoreMap":133},[137,550,551],{"class":139,"line":140},[137,552,545],{},[99,554,555],{},"Attach a Node debugger to the address Nuxt prints, then open the original Scala file in Sources. Handlers run in Node, so use the server's inspector session, not the browser page. Source maps give locations and source views. They do not give Scala expression evaluation or a JVM-style debugger. Breakpoint stepping has not been verified.",[111,557,559],{"id":558},"rebuild-after-editing","Rebuild after editing",[99,561,562,563,566,567,570],{},"Run ",[119,564,565],{},"pnpm run scala:fast"," after a Scala change, or keep ",[119,568,569],{},"pnpm run scala:watch"," running. Wait until linking finishes and Nitro restarts its worker before you send the next request. If a stack frame looks stale, check that linking succeeded and the generated files changed.",[111,572,574],{"id":573},"checks","Checks",[128,576,578],{"className":544,"code":577,"language":546,"meta":133,"style":133},"node --test scripts\u002F*.test.mjs packages\u002Fnuxt\u002Ftest\u002F*.test.mjs\n",[119,579,580],{"__ignoreMap":133},[137,581,582],{"class":139,"line":140},[137,583,577],{},[99,585,586,587,590,591,593,594,263,596,278],{},"These Node tests pass on macOS x86_64 with Node 24.19.0 (see ",[106,588,589],{"href":87},"compatibility","). They cover the development resolver, Rollup-to-Node source maps, map composition, the Nitro plugin's records and flags, the debug flag merge in the Nuxt module, and the close hook. The Scala suites cover opaque 500s, development and debug diagnostics, Kyo stack text and ZIO ",[119,592,257],{}," with Scala file names, and that ",[119,595,125],{},[119,597,266],{},[99,599,600,601,604,605,607,608,611,612,614,615,618,619,459,622,625,626,629,630,632],{},"On this branch (macOS x86_64, Node 24.19.0, Nuxt 4.3.1), ",[119,602,603],{},"pnpm dev"," after ",[119,606,565],{}," answered ",[119,609,610],{},"\u002Fapi\u002Fnotes"," without a database with a 500 whose ",[119,613,424],{}," had Scala stack frames and no password, and a Kyo handler that threw a JavaScript ",[119,616,617],{},"TypeError"," had its stack mapped to ",[119,620,621],{},"RequestLifecycle.scala",[119,623,624],{},"KHandler.scala",". ",[119,627,628],{},"scripts\u002Fcheck-npm-nuxt.mjs"," checked development diagnostics, source maps and a relink reload with the packed module on a synthetic project. Relinking the real Scala.js example under ",[119,631,342],{}," and breakpoint stepping have not been checked.",[634,635,636],"style",{},"html pre.shiki code .sxrX7, html code.shiki .sxrX7{--shiki-light:#24292E;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sBjJW, html code.shiki .sBjJW{--shiki-light:#005CC5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sIIMD, html code.shiki .sIIMD{--shiki-light:#032F62;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .snPdu, html code.shiki .snPdu{--shiki-light:#6F42C1;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s8jYJ, html code.shiki .s8jYJ{--shiki-light:#D73A49;--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":133,"searchDepth":180,"depth":180,"links":638},[639,640,641,642,643,644],{"id":113,"depth":180,"text":114},{"id":288,"depth":180,"text":289},{"id":431,"depth":180,"text":432},{"id":537,"depth":180,"text":538},{"id":558,"depth":180,"text":559},{"id":573,"depth":180,"text":574},"See error causes in development or debug mode, keep production opaque, and map Nitro's JavaScript back to Scala.","md",null,{},true,{"title":59,"description":645},"UO04c6GuwiEoOSI0MEbSNNf1-T5m6ciIRwa7i2KKH6M",[653,655],{"title":55,"path":56,"stem":57,"description":654,"children":-1},"Open a Nitro storage mount from Scala with KHubKv.mount or ZHubKv.mount, with no native objects.",{"title":63,"path":64,"stem":65,"description":656,"children":-1},"Configure the shared Scala.js CLI and Nuxt module, including the Nitro plugin that supplies config, storage and shutdown to Scala.",1792533381917]