[{"data":1,"prerenderedAt":2842},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fbuilding\u002Ferror-handling-dlq":314,"\u002Fdocs\u002Fbuilding\u002Ferror-handling-dlq-surround":2837},[4,38,86,149,176,219,257,273],{"title":5,"path":6,"stem":7,"children":8,"icon":37},"Getting Started","\u002Fdocs\u002Fgetting-started","1.docs\u002F1.getting-started\u002F1.index",[9,12,17,22,27,32],{"title":10,"path":6,"stem":7,"icon":11},"Getting started","i-lucide-flag",{"title":13,"path":14,"stem":15,"icon":16},"Modules overview","\u002Fdocs\u002Fgetting-started\u002Fmodules-overview","1.docs\u002F1.getting-started\u002F2.modules-overview","i-lucide-boxes",{"title":18,"path":19,"stem":20,"icon":21},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","1.docs\u002F1.getting-started\u002F3.installation","i-lucide-download",{"title":23,"path":24,"stem":25,"icon":26},"License configuration","\u002Fdocs\u002Fgetting-started\u002Flicense-configuration","1.docs\u002F1.getting-started\u002F4.license-configuration","i-lucide-key-round",{"title":28,"path":29,"stem":30,"icon":31},"Your first app","\u002Fdocs\u002Fgetting-started\u002Ffirst-app","1.docs\u002F1.getting-started\u002F5.first-app","i-lucide-square-play",{"title":33,"path":34,"stem":35,"icon":36},"Project setup","\u002Fdocs\u002Fgetting-started\u002Fproject-setup","1.docs\u002F1.getting-started\u002F6.project-setup","i-lucide-package",false,{"title":39,"path":40,"stem":41,"children":42,"icon":45},"Core Concepts","\u002Fdocs\u002Fconcepts","1.docs\u002F2.concepts\u002F1.index",[43,46,51,56,61,66,71,76,81],{"title":44,"path":40,"stem":41,"icon":45},"Core concepts","i-lucide-book-open",{"title":47,"path":48,"stem":49,"icon":50},"Architecture","\u002Fdocs\u002Fconcepts\u002Farchitecture","1.docs\u002F2.concepts\u002F2.architecture","i-lucide-layers",{"title":52,"path":53,"stem":54,"icon":55},"Exactly-once semantics","\u002Fdocs\u002Fconcepts\u002Fexactly-once","1.docs\u002F2.concepts\u002F3.exactly-once","i-lucide-shield-check",{"title":57,"path":58,"stem":59,"icon":60},"Lanes and parallelism","\u002Fdocs\u002Fconcepts\u002Flanes-and-parallelism","1.docs\u002F2.concepts\u002F4.lanes-and-parallelism","i-lucide-split",{"title":62,"path":63,"stem":64,"icon":65},"State and thread-safety","\u002Fdocs\u002Fconcepts\u002Fstate-and-thread-safety","1.docs\u002F2.concepts\u002F5.state-and-thread-safety","i-lucide-lock",{"title":67,"path":68,"stem":69,"icon":70},"Event time and watermarks","\u002Fdocs\u002Fconcepts\u002Fevent-time-and-watermarks","1.docs\u002F2.concepts\u002F6.event-time-and-watermarks","i-lucide-clock",{"title":72,"path":73,"stem":74,"icon":75},"The configuration model","\u002Fdocs\u002Fconcepts\u002Fconfiguration-model","1.docs\u002F2.concepts\u002F7.configuration-model","i-lucide-sliders-horizontal",{"title":77,"path":78,"stem":79,"icon":80},"The error-handling model","\u002Fdocs\u002Fconcepts\u002Ferror-handling-model","1.docs\u002F2.concepts\u002F8.error-handling-model","i-lucide-triangle-alert",{"title":82,"path":83,"stem":84,"icon":85},"How StoatFlow differs from Kafka Streams","\u002Fdocs\u002Fconcepts\u002Fhow-stoatflow-differs-from-ks","1.docs\u002F2.concepts\u002F9.how-stoatflow-differs-from-ks","i-lucide-arrow-left-right",{"title":87,"path":88,"stem":89,"children":90,"icon":93},"Building Topologies","\u002Fdocs\u002Fbuilding","1.docs\u002F3.building\u002F1.index",[91,94,99,104,109,114,119,124,129,134,139,144],{"title":92,"path":88,"stem":89,"icon":93},"Building topologies","i-lucide-blocks",{"title":95,"path":96,"stem":97,"icon":98},"Error handling and DLQ","\u002Fdocs\u002Fbuilding\u002Ferror-handling-dlq","1.docs\u002F3.building\u002F10.error-handling-dlq","i-lucide-circle-x",{"title":100,"path":101,"stem":102,"icon":103},"State stores","\u002Fdocs\u002Fbuilding\u002Fstate-stores","1.docs\u002F3.building\u002F11.state-stores","i-lucide-database",{"title":105,"path":106,"stem":107,"icon":108},"Testing topologies","\u002Fdocs\u002Fbuilding\u002Ftesting","1.docs\u002F3.building\u002F12.testing","i-lucide-flask-conical",{"title":110,"path":111,"stem":112,"icon":113},"Sources and sinks","\u002Fdocs\u002Fbuilding\u002Fstreams-builder","1.docs\u002F3.building\u002F2.streams-builder","i-lucide-import",{"title":115,"path":116,"stem":117,"icon":118},"KStream and KTable operations","\u002Fdocs\u002Fbuilding\u002Fkstream-ktable","1.docs\u002F3.building\u002F3.kstream-ktable","i-lucide-waypoints",{"title":120,"path":121,"stem":122,"icon":123},"Aggregations","\u002Fdocs\u002Fbuilding\u002Faggregations","1.docs\u002F3.building\u002F4.aggregations","i-lucide-sigma",{"title":125,"path":126,"stem":127,"icon":128},"Windowing","\u002Fdocs\u002Fbuilding\u002Fwindowing","1.docs\u002F3.building\u002F5.windowing","i-lucide-calendar-clock",{"title":130,"path":131,"stem":132,"icon":133},"Joins","\u002Fdocs\u002Fbuilding\u002Fjoins","1.docs\u002F3.building\u002F6.joins","i-lucide-git-merge",{"title":135,"path":136,"stem":137,"icon":138},"The Processor API","\u002Fdocs\u002Fbuilding\u002Fprocessor-api","1.docs\u002F3.building\u002F7.processor-api","i-lucide-cpu",{"title":140,"path":141,"stem":142,"icon":143},"Scheduled sources","\u002Fdocs\u002Fbuilding\u002Fscheduled-sources","1.docs\u002F3.building\u002F8.scheduled-sources","i-lucide-timer",{"title":145,"path":146,"stem":147,"icon":148},"Serdes and Avro","\u002Fdocs\u002Fbuilding\u002Fserdes","1.docs\u002F3.building\u002F9.serdes","i-lucide-binary",{"title":150,"path":151,"stem":152,"children":153,"icon":75},"Configuration","\u002Fdocs\u002Fconfiguration","1.docs\u002F4.configuration\u002F1.index",[154,156,161,166,171],{"title":155,"path":151,"stem":152,"icon":75},"How configuration works",{"title":157,"path":158,"stem":159,"icon":160},"Engine configuration (:core)","\u002Fdocs\u002Fconfiguration\u002Fcore-config","1.docs\u002F4.configuration\u002F2.core-config","i-lucide-settings-2",{"title":162,"path":163,"stem":164,"icon":165},"Runtime configuration (:runtime)","\u002Fdocs\u002Fconfiguration\u002Fruntime-config","1.docs\u002F4.configuration\u002F3.runtime-config","i-lucide-server-cog",{"title":167,"path":168,"stem":169,"icon":170},"Defaults, adaptivity, and presets","\u002Fdocs\u002Fconfiguration\u002Fdefaults-and-presets","1.docs\u002F4.configuration\u002F4.defaults-and-presets","i-lucide-gauge",{"title":172,"path":173,"stem":174,"icon":175},"Kafka client configuration","\u002Fdocs\u002Fconfiguration\u002Fkafka-client-config","1.docs\u002F4.configuration\u002F5.kafka-client-config","i-lucide-plug",{"title":177,"path":178,"stem":179,"children":180,"icon":183},"Running in Production","\u002Fdocs\u002Fruntime","1.docs\u002F5.runtime\u002F1.index",[181,184,189,194,199,204,209,214],{"title":182,"path":178,"stem":179,"icon":183},"The runtime","i-lucide-server",{"title":185,"path":186,"stem":187,"icon":188},"The REST API","\u002Fdocs\u002Fruntime\u002Frest-api","1.docs\u002F5.runtime\u002F2.rest-api","i-lucide-globe",{"title":190,"path":191,"stem":192,"icon":193},"Health checks","\u002Fdocs\u002Fruntime\u002Fhealth-checks","1.docs\u002F5.runtime\u002F3.health-checks","i-lucide-heart-pulse",{"title":195,"path":196,"stem":197,"icon":198},"Metrics","\u002Fdocs\u002Fruntime\u002Fmetrics","1.docs\u002F5.runtime\u002F4.metrics","i-lucide-activity",{"title":200,"path":201,"stem":202,"icon":203},"Pause and resume","\u002Fdocs\u002Fruntime\u002Fpause-unpause","1.docs\u002F5.runtime\u002F5.pause-unpause","i-lucide-pause",{"title":205,"path":206,"stem":207,"icon":208},"Plugins and lifecycle hooks","\u002Fdocs\u002Fruntime\u002Fplugins","1.docs\u002F5.runtime\u002F6.plugins","i-lucide-puzzle",{"title":210,"path":211,"stem":212,"icon":213},"Docker images","\u002Fdocs\u002Fruntime\u002Fdocker","1.docs\u002F5.runtime\u002F7.docker","i-lucide-container",{"title":215,"path":216,"stem":217,"icon":218},"GraalVM native image","\u002Fdocs\u002Fruntime\u002Fnative-image","1.docs\u002F5.runtime\u002F8.native-image","i-lucide-zap",{"title":220,"path":221,"stem":222,"children":223,"icon":226},"Deploying & Operating","\u002Fdocs\u002Foperating","1.docs\u002F6.operating\u002F1.index",[224,227,232,237,242,247,252],{"title":225,"path":221,"stem":222,"icon":226},"Deploying and operating","i-lucide-life-buoy",{"title":228,"path":229,"stem":230,"icon":231},"Running on Kubernetes","\u002Fdocs\u002Foperating\u002Fkubernetes","1.docs\u002F6.operating\u002F2.kubernetes","i-lucide-ship",{"title":233,"path":234,"stem":235,"icon":236},"High availability","\u002Fdocs\u002Foperating\u002Fhigh-availability","1.docs\u002F6.operating\u002F3.high-availability","i-lucide-copy",{"title":238,"path":239,"stem":240,"icon":241},"Liveness and readiness probes","\u002Fdocs\u002Foperating\u002Fprobes","1.docs\u002F6.operating\u002F4.probes","i-lucide-stethoscope",{"title":243,"path":244,"stem":245,"icon":246},"Observability","\u002Fdocs\u002Foperating\u002Fobservability","1.docs\u002F6.operating\u002F5.observability","i-lucide-telescope",{"title":248,"path":249,"stem":250,"icon":251},"Tuning under load","\u002Fdocs\u002Foperating\u002Ftuning","1.docs\u002F6.operating\u002F6.tuning","i-lucide-sliders",{"title":253,"path":254,"stem":255,"icon":256},"Production checklist","\u002Fdocs\u002Foperating\u002Fproduction-checklist","1.docs\u002F6.operating\u002F7.production-checklist","i-lucide-clipboard-check",{"title":258,"path":259,"stem":260,"children":261,"icon":85},"Migrating from Kafka Streams","\u002Fdocs\u002Fmigration","1.docs\u002F7.migration\u002F1.index",[262,263,268],{"title":258,"path":259,"stem":260,"icon":85},{"title":264,"path":265,"stem":266,"icon":267},"Migration without carrying state","\u002Fdocs\u002Fmigration\u002Fwithout-data-migration","1.docs\u002F7.migration\u002F2.without-data-migration","i-lucide-sparkles",{"title":269,"path":270,"stem":271,"icon":272},"Migration carrying state","\u002Fdocs\u002Fmigration\u002Fwith-data-migration","1.docs\u002F7.migration\u002F3.with-data-migration","i-lucide-database-backup",{"title":274,"path":275,"stem":276,"children":277,"icon":279},"Reference","\u002Fdocs\u002Freference","1.docs\u002F8.reference\u002F1.index",[278,280,285,290,295,300,305,309],{"title":274,"path":275,"stem":276,"icon":279},"i-lucide-list",{"title":281,"path":282,"stem":283,"icon":284},"Configuration reference","\u002Fdocs\u002Freference\u002Fconfiguration-reference","1.docs\u002F8.reference\u002F2.configuration-reference","i-lucide-table",{"title":286,"path":287,"stem":288,"icon":289},"REST API reference","\u002Fdocs\u002Freference\u002Frest-api-reference","1.docs\u002F8.reference\u002F3.rest-api-reference","i-lucide-network",{"title":291,"path":292,"stem":293,"icon":294},"Gradle plugin reference","\u002Fdocs\u002Freference\u002Fgradle-plugin-reference","1.docs\u002F8.reference\u002F4.gradle-plugin-reference","i-lucide-box",{"title":296,"path":297,"stem":298,"icon":299},"Maven reference","\u002Fdocs\u002Freference\u002Fmaven-reference","1.docs\u002F8.reference\u002F5.maven-reference","i-simple-icons-apachemaven",{"title":301,"path":302,"stem":303,"icon":304},"Kafka Streams compatibility matrix","\u002Fdocs\u002Freference\u002Fks-compatibility-matrix","1.docs\u002F8.reference\u002F6.ks-compatibility-matrix","i-lucide-table-2",{"title":306,"path":307,"stem":308,"icon":170},"Metrics reference","\u002Fdocs\u002Freference\u002Fmetrics-reference","1.docs\u002F8.reference\u002F7.metrics-reference",{"title":310,"path":311,"stem":312,"icon":313},"Glossary","\u002Fdocs\u002Freference\u002Fglossary","1.docs\u002F8.reference\u002F8.glossary","i-lucide-book-a",{"id":315,"title":95,"body":316,"description":2830,"extension":2831,"meta":2832,"navigation":2833,"pageType":2834,"path":96,"seo":2835,"stem":97,"__hash__":2836},"docs\u002F1.docs\u002F3.building\u002F10.error-handling-dlq.md",{"type":317,"value":318,"toc":2817},"minimark",[319,345,353,402,407,487,490,519,535,539,545,660,668,672,690,693,1258,1261,1370,1387,1391,1405,1473,1493,1497,1511,1514,1539,1544,1554,1755,1758,1812,1816,1840,1843,1895,1905,1909,1944,2348,2363,2366,2370,2385,2777,2784,2788,2813],[320,321,322,323,327,328,331,332,335,336,340,341,344],"p",{},"StoatFlow has three independent exception handlers, one per failure stage: a record that fails to ",[324,325,326],"strong",{},"deserialize"," on the way in, a ",[324,329,330],{},"processor"," that throws while handling a record, and a ",[324,333,334],{},"production"," failure when serializing or sending an output record. Each handler decides whether to skip the record and continue, stop the application, or route the record to a dead-letter queue (DLQ) — and each is wired the same way, in code via ",[337,338,339],"code",{},"streamsConfigOverrides"," or in ",[337,342,343],{},"application.yaml"," by class name.",[320,346,347,348,352],{},"For the design rationale — why these three stages, when \"continue\" is safe, and how DLQ records ride the same commit barrier as your output — see ",[349,350,351],"a",{"href":78},"Error-handling model",".",[354,355,356],"tldr-panel",{},[357,358,359,376,382,392],"ul",{},[360,361,362,365,366,369,370,369,373,352],"li",{},[324,363,364],{},"Three handlers:"," ",[337,367,368],{},"deserializationExceptionHandler",", ",[337,371,372],{},"processingExceptionHandler",[337,374,375],{},"productionExceptionHandler",[360,377,378,381],{},[324,379,380],{},"Built-in behaviours:"," log-and-fail (default for deser + processing), log-and-continue, and dead-letter-queue.",[360,383,384,387,388,391],{},[324,385,386],{},"DLQ records"," carry the original bytes plus error metadata in ",[337,389,390],{},"__stoatflow.errors.*"," headers, and are committed transactionally alongside your normal output.",[360,393,394,397,398,401],{},[324,395,396],{},"Wire it:"," in code via ",[337,399,400],{},"streamsConfigOverrides { ... }",", or in YAML by fully qualified class name (no-arg handlers only).",[403,404,406],"h2",{"id":405},"the-three-handler-stages","The three handler stages",[408,409,410,429],"table",{},[411,412,413],"thead",{},[414,415,416,420,423,426],"tr",{},[417,418,419],"th",{},"Stage",[417,421,422],{},"Config property",[417,424,425],{},"Fires when",[417,427,428],{},"Default",[430,431,432,450,470],"tbody",{},[414,433,434,438,442,445],{},[435,436,437],"td",{},"Deserialization",[435,439,440],{},[337,441,368],{},[435,443,444],{},"A source record's key or value cannot be deserialized",[435,446,447],{},[337,448,449],{},"LogAndFailDeserializationExceptionHandler",[414,451,452,455,459,465],{},[435,453,454],{},"Processing",[435,456,457],{},[337,458,372],{},[435,460,461,462],{},"A processor throws during ",[337,463,464],{},"process()",[435,466,467],{},[337,468,469],{},"LogAndFailProcessingExceptionHandler",[414,471,472,475,479,482],{},[435,473,474],{},"Production",[435,476,477],{},[337,478,375],{},[435,480,481],{},"An output record fails to serialize or send",[435,483,484],{},[337,485,486],{},"DefaultProductionExceptionHandler",[320,488,489],{},"Each handler returns a decision:",[357,491,492,500,511],{},[360,493,494,499],{},[324,495,496],{},[337,497,498],{},"CONTINUE"," — skip the failed record and keep processing. Optionally emit one or more DLQ records.",[360,501,502,507,508,510],{},[324,503,504],{},[337,505,506],{},"FAIL"," — stop the application. The in-flight epoch's work is discarded and the process exits; see ",[349,509,47],{"href":48}," for the recovery behaviour on restart. Optionally emit DLQ records before failing.",[360,512,513,518],{},[324,514,515],{},[337,516,517],{},"RETRY"," — production handlers only. Retry the send for transient, retriable errors before giving up.",[520,521,524],"callout",{"color":522,"icon":523},"warning","i-lucide-alert-triangle",[320,525,526,527,530,531,534],{},"The deserialization and processing defaults are ",[324,528,529],{},"fail-fast"," (",[337,532,533],{},"LogAndFail*","). A malformed record stops the application until you choose a continue-or-DLQ policy — StoatFlow does not silently drop data unless you opt in.",[403,536,538],{"id":537},"built-in-handlers","Built-in handlers",[320,540,541,542,352],{},"All built-in handlers live in ",[337,543,544],{},"io.stoatflow.core.exception",[408,546,547,559],{},[411,548,549],{},[414,550,551,554,556],{},[417,552,553],{},"Handler class",[417,555,419],{},[417,557,558],{},"Behaviour",[430,560,561,575,590,604,616,629,642],{},[414,562,563,567,569],{},[435,564,565],{},[337,566,449],{},[435,568,437],{},[435,570,571,572,574],{},"Log at error, then ",[337,573,506],{}," (default)",[414,576,577,582,584],{},[435,578,579],{},[337,580,581],{},"LogAndContinueDeserializationExceptionHandler",[435,583,437],{},[435,585,586,587,589],{},"Log at warn, then ",[337,588,498],{}," (record skipped)",[414,591,592,597,599],{},[435,593,594],{},[337,595,596],{},"DeadLetterQueueDeserializationExceptionHandler",[435,598,437],{},[435,600,601,602],{},"Log at warn, emit DLQ record, then ",[337,603,498],{},[414,605,606,610,612],{},[435,607,608],{},[337,609,469],{},[435,611,454],{},[435,613,571,614,574],{},[337,615,506],{},[414,617,618,623,625],{},[435,619,620],{},[337,621,622],{},"LogAndContinueProcessingExceptionHandler",[435,624,454],{},[435,626,586,627,589],{},[337,628,498],{},[414,630,631,636,638],{},[435,632,633],{},[337,634,635],{},"DeadLetterQueueProcessingExceptionHandler",[435,637,454],{},[435,639,601,640],{},[337,641,498],{},[414,643,644,648,650],{},[435,645,646],{},[337,647,486],{},[435,649,474],{},[435,651,652,653,655,656,659],{},"Retry retriable send errors; ",[337,654,506],{}," on serialization and non-retriable send errors; route to DLQ first if a ",[337,657,658],{},"dlqTopic"," is set (default)",[320,661,662,664,665,667],{},[337,663,486],{}," is the only built-in production handler; it covers retry-vs-fail classification and optional DLQ routing in one place, so you configure behaviour by whether you pass it a ",[337,666,658],{}," rather than by swapping the class.",[403,669,671],{"id":670},"configuring-a-handler-in-code","Configuring a handler in code",[320,673,674,675,677,678,681,682,685,686,689],{},"Set handlers through ",[337,676,339],{}," on the ",[337,679,680],{},":runtime"," builder. The same builder methods exist on ",[337,683,684],{},"StreamsConfig.builder(...)"," if you run on ",[337,687,688],{},":core"," directly.",[320,691,692],{},"This example routes deserialization failures to a DLQ topic (skip + capture), keeps the fail-fast processing default, and adds a DLQ topic for production failures:",[694,695,697,942],"code-tabs",{"group":696},"lang",[698,699,705],"pre",{"className":700,"code":701,"filename":702,"language":703,"meta":704,"style":704},"language-kotlin shiki shiki-themes vitesse-light","import io.stoatflow.core.exception.DeadLetterQueueDeserializationExceptionHandler\nimport io.stoatflow.core.exception.DefaultProductionExceptionHandler\nimport io.stoatflow.runtime.StoatFlowRuntime\nimport org.apache.kafka.common.serialization.Serdes\n\nval runtime = StoatFlowRuntime.fromConfig(\n    topologyBuilder = { buildTopology(it) },\n    configure = {\n        streamsConfigOverrides {\n            defaultKeySerde(Serdes.String())\n            defaultValueSerde(Serdes.String())\n\n            deserializationExceptionHandler(\n                DeadLetterQueueDeserializationExceptionHandler(dlqTopic = \"my-app.deserialization-errors.dlq\"),\n            )\n            productionExceptionHandler(\n                DefaultProductionExceptionHandler(dlqTopic = \"my-app.production-errors.dlq\"),\n            )\n        }\n    },\n)\nruntime.start()\nruntime.awaitTermination()\n","Kotlin","kotlin","",[337,706,707,720,728,736,744,751,774,791,802,810,825,837,842,850,868,874,882,897,902,908,914,920,932],{"__ignoreMap":704},[708,709,712,716],"span",{"class":710,"line":711},"line",1,[708,713,715],{"class":714},"sbBg2","import",[708,717,719],{"class":718},"sySUi"," io.stoatflow.core.exception.DeadLetterQueueDeserializationExceptionHandler\n",[708,721,723,725],{"class":710,"line":722},2,[708,724,715],{"class":714},[708,726,727],{"class":718}," io.stoatflow.core.exception.DefaultProductionExceptionHandler\n",[708,729,731,733],{"class":710,"line":730},3,[708,732,715],{"class":714},[708,734,735],{"class":718}," io.stoatflow.runtime.StoatFlowRuntime\n",[708,737,739,741],{"class":710,"line":738},4,[708,740,715],{"class":714},[708,742,743],{"class":718}," org.apache.kafka.common.serialization.Serdes\n",[708,745,747],{"class":710,"line":746},5,[708,748,750],{"emptyLinePlaceholder":749},true,"\n",[708,752,754,757,761,765,768,771],{"class":710,"line":753},6,[708,755,756],{"class":714},"val",[708,758,760],{"class":759},"suHK_"," runtime ",[708,762,764],{"class":763},"sYZai","=",[708,766,767],{"class":759}," StoatFlowRuntime.",[708,769,770],{"class":718},"fromConfig",[708,772,773],{"class":759},"(\n",[708,775,777,780,782,785,788],{"class":710,"line":776},7,[708,778,779],{"class":759},"    topologyBuilder ",[708,781,764],{"class":763},[708,783,784],{"class":759}," { ",[708,786,787],{"class":718},"buildTopology",[708,789,790],{"class":759},"(it) },\n",[708,792,794,797,799],{"class":710,"line":793},8,[708,795,796],{"class":759},"    configure ",[708,798,764],{"class":763},[708,800,801],{"class":759}," {\n",[708,803,805,808],{"class":710,"line":804},9,[708,806,807],{"class":718},"        streamsConfigOverrides",[708,809,801],{"class":759},[708,811,813,816,819,822],{"class":710,"line":812},10,[708,814,815],{"class":718},"            defaultKeySerde",[708,817,818],{"class":759},"(Serdes.",[708,820,821],{"class":718},"String",[708,823,824],{"class":759},"())\n",[708,826,828,831,833,835],{"class":710,"line":827},11,[708,829,830],{"class":718},"            defaultValueSerde",[708,832,818],{"class":759},[708,834,821],{"class":718},[708,836,824],{"class":759},[708,838,840],{"class":710,"line":839},12,[708,841,750],{"emptyLinePlaceholder":749},[708,843,845,848],{"class":710,"line":844},13,[708,846,847],{"class":718},"            deserializationExceptionHandler",[708,849,773],{"class":759},[708,851,853,856,859,861,865],{"class":710,"line":852},14,[708,854,855],{"class":718},"                DeadLetterQueueDeserializationExceptionHandler",[708,857,858],{"class":759},"(dlqTopic ",[708,860,764],{"class":763},[708,862,864],{"class":863},"spphp"," \"my-app.deserialization-errors.dlq\"",[708,866,867],{"class":759},"),\n",[708,869,871],{"class":710,"line":870},15,[708,872,873],{"class":759},"            )\n",[708,875,877,880],{"class":710,"line":876},16,[708,878,879],{"class":718},"            productionExceptionHandler",[708,881,773],{"class":759},[708,883,885,888,890,892,895],{"class":710,"line":884},17,[708,886,887],{"class":718},"                DefaultProductionExceptionHandler",[708,889,858],{"class":759},[708,891,764],{"class":763},[708,893,894],{"class":863}," \"my-app.production-errors.dlq\"",[708,896,867],{"class":759},[708,898,900],{"class":710,"line":899},18,[708,901,873],{"class":759},[708,903,905],{"class":710,"line":904},19,[708,906,907],{"class":759},"        }\n",[708,909,911],{"class":710,"line":910},20,[708,912,913],{"class":759},"    },\n",[708,915,917],{"class":710,"line":916},21,[708,918,919],{"class":759},")\n",[708,921,923,926,929],{"class":710,"line":922},22,[708,924,925],{"class":759},"runtime.",[708,927,928],{"class":718},"start",[708,930,931],{"class":759},"()\n",[708,933,935,937,940],{"class":710,"line":934},23,[708,936,925],{"class":759},[708,938,939],{"class":718},"awaitTermination",[708,941,931],{"class":759},[698,943,948],{"className":944,"code":945,"filename":946,"language":947,"meta":704,"style":704},"language-java shiki shiki-themes vitesse-light","import io.stoatflow.core.exception.DeadLetterQueueDeserializationExceptionHandler;\nimport io.stoatflow.core.exception.DefaultProductionExceptionHandler;\nimport io.stoatflow.runtime.StoatFlowRuntime;\nimport org.apache.kafka.common.serialization.Serdes;\n\nvar runtime = StoatFlowRuntime.fromConfig(\n    Main::buildTopology,\n    builder -> builder.streamsConfigOverrides(cfg -> {\n        cfg.defaultKeySerde(Serdes.String());\n        cfg.defaultValueSerde(Serdes.String());\n\n        cfg.deserializationExceptionHandler(\n            new DeadLetterQueueDeserializationExceptionHandler(\"my-app.deserialization-errors.dlq\"));\n        cfg.productionExceptionHandler(\n            new DefaultProductionExceptionHandler(\"my-app.production-errors.dlq\"));\n    })\n);\nruntime.start();\nruntime.awaitTermination();\n","Java","java",[337,949,950,979,1003,1025,1059,1063,1085,1098,1123,1144,1163,1167,1177,1199,1209,1227,1232,1237,1248],{"__ignoreMap":704},[708,951,952,954,957,959,962,964,967,969,972,974,976],{"class":710,"line":711},[708,953,715],{"class":714},[708,955,956],{"class":759}," io",[708,958,352],{"class":763},[708,960,961],{"class":759},"stoatflow",[708,963,352],{"class":763},[708,965,966],{"class":759},"core",[708,968,352],{"class":763},[708,970,971],{"class":759},"exception",[708,973,352],{"class":763},[708,975,596],{"class":759},[708,977,978],{"class":763},";\n",[708,980,981,983,985,987,989,991,993,995,997,999,1001],{"class":710,"line":722},[708,982,715],{"class":714},[708,984,956],{"class":759},[708,986,352],{"class":763},[708,988,961],{"class":759},[708,990,352],{"class":763},[708,992,966],{"class":759},[708,994,352],{"class":763},[708,996,971],{"class":759},[708,998,352],{"class":763},[708,1000,486],{"class":759},[708,1002,978],{"class":763},[708,1004,1005,1007,1009,1011,1013,1015,1018,1020,1023],{"class":710,"line":730},[708,1006,715],{"class":714},[708,1008,956],{"class":759},[708,1010,352],{"class":763},[708,1012,961],{"class":759},[708,1014,352],{"class":763},[708,1016,1017],{"class":759},"runtime",[708,1019,352],{"class":763},[708,1021,1022],{"class":759},"StoatFlowRuntime",[708,1024,978],{"class":763},[708,1026,1027,1029,1032,1034,1037,1039,1042,1044,1047,1049,1052,1054,1057],{"class":710,"line":738},[708,1028,715],{"class":714},[708,1030,1031],{"class":759}," org",[708,1033,352],{"class":763},[708,1035,1036],{"class":759},"apache",[708,1038,352],{"class":763},[708,1040,1041],{"class":759},"kafka",[708,1043,352],{"class":763},[708,1045,1046],{"class":759},"common",[708,1048,352],{"class":763},[708,1050,1051],{"class":759},"serialization",[708,1053,352],{"class":763},[708,1055,1056],{"class":759},"Serdes",[708,1058,978],{"class":763},[708,1060,1061],{"class":710,"line":746},[708,1062,750],{"emptyLinePlaceholder":749},[708,1064,1065,1069,1073,1076,1079,1081,1083],{"class":710,"line":753},[708,1066,1068],{"class":1067},"si04Y","var",[708,1070,1072],{"class":1071},"svycV"," runtime",[708,1074,1075],{"class":763}," =",[708,1077,1078],{"class":1071}," StoatFlowRuntime",[708,1080,352],{"class":763},[708,1082,770],{"class":718},[708,1084,773],{"class":763},[708,1086,1087,1090,1093,1095],{"class":710,"line":776},[708,1088,1089],{"class":759},"    Main",[708,1091,1092],{"class":714},"::",[708,1094,787],{"class":759},[708,1096,1097],{"class":763},",\n",[708,1099,1100,1103,1106,1109,1111,1113,1116,1119,1121],{"class":710,"line":793},[708,1101,1102],{"class":759},"    builder ",[708,1104,1105],{"class":763},"->",[708,1107,1108],{"class":1071}," builder",[708,1110,352],{"class":763},[708,1112,339],{"class":718},[708,1114,1115],{"class":763},"(",[708,1117,1118],{"class":759},"cfg ",[708,1120,1105],{"class":763},[708,1122,801],{"class":763},[708,1124,1125,1128,1130,1133,1135,1137,1139,1141],{"class":710,"line":804},[708,1126,1127],{"class":1071},"        cfg",[708,1129,352],{"class":763},[708,1131,1132],{"class":718},"defaultKeySerde",[708,1134,1115],{"class":763},[708,1136,1056],{"class":1071},[708,1138,352],{"class":763},[708,1140,821],{"class":718},[708,1142,1143],{"class":763},"());\n",[708,1145,1146,1148,1150,1153,1155,1157,1159,1161],{"class":710,"line":812},[708,1147,1127],{"class":1071},[708,1149,352],{"class":763},[708,1151,1152],{"class":718},"defaultValueSerde",[708,1154,1115],{"class":763},[708,1156,1056],{"class":1071},[708,1158,352],{"class":763},[708,1160,821],{"class":718},[708,1162,1143],{"class":763},[708,1164,1165],{"class":710,"line":827},[708,1166,750],{"emptyLinePlaceholder":749},[708,1168,1169,1171,1173,1175],{"class":710,"line":839},[708,1170,1127],{"class":1071},[708,1172,352],{"class":763},[708,1174,368],{"class":718},[708,1176,773],{"class":763},[708,1178,1179,1182,1185,1187,1191,1194,1196],{"class":710,"line":844},[708,1180,1181],{"class":714},"            new",[708,1183,1184],{"class":718}," DeadLetterQueueDeserializationExceptionHandler",[708,1186,1115],{"class":763},[708,1188,1190],{"class":1189},"sSP4y","\"",[708,1192,1193],{"class":863},"my-app.deserialization-errors.dlq",[708,1195,1190],{"class":1189},[708,1197,1198],{"class":763},"));\n",[708,1200,1201,1203,1205,1207],{"class":710,"line":852},[708,1202,1127],{"class":1071},[708,1204,352],{"class":763},[708,1206,375],{"class":718},[708,1208,773],{"class":763},[708,1210,1211,1213,1216,1218,1220,1223,1225],{"class":710,"line":870},[708,1212,1181],{"class":714},[708,1214,1215],{"class":718}," DefaultProductionExceptionHandler",[708,1217,1115],{"class":763},[708,1219,1190],{"class":1189},[708,1221,1222],{"class":863},"my-app.production-errors.dlq",[708,1224,1190],{"class":1189},[708,1226,1198],{"class":763},[708,1228,1229],{"class":710,"line":876},[708,1230,1231],{"class":763},"    })\n",[708,1233,1234],{"class":710,"line":884},[708,1235,1236],{"class":763},");\n",[708,1238,1239,1241,1243,1245],{"class":710,"line":899},[708,1240,1017],{"class":1071},[708,1242,352],{"class":763},[708,1244,928],{"class":718},[708,1246,1247],{"class":763},"();\n",[708,1249,1250,1252,1254,1256],{"class":710,"line":904},[708,1251,1017],{"class":1071},[708,1253,352],{"class":763},[708,1255,939],{"class":718},[708,1257,1247],{"class":763},[320,1259,1260],{},"To skip bad records without a DLQ, swap in the log-and-continue handler instead:",[694,1262,1263,1301],{"group":696},[698,1264,1266],{"className":700,"code":1265,"filename":702,"language":703,"meta":704,"style":704},"import io.stoatflow.core.exception.LogAndContinueDeserializationExceptionHandler\n\nstreamsConfigOverrides {\n    deserializationExceptionHandler(LogAndContinueDeserializationExceptionHandler())\n}\n",[337,1267,1268,1275,1279,1285,1296],{"__ignoreMap":704},[708,1269,1270,1272],{"class":710,"line":711},[708,1271,715],{"class":714},[708,1273,1274],{"class":718}," io.stoatflow.core.exception.LogAndContinueDeserializationExceptionHandler\n",[708,1276,1277],{"class":710,"line":722},[708,1278,750],{"emptyLinePlaceholder":749},[708,1280,1281,1283],{"class":710,"line":730},[708,1282,339],{"class":718},[708,1284,801],{"class":759},[708,1286,1287,1290,1292,1294],{"class":710,"line":738},[708,1288,1289],{"class":718},"    deserializationExceptionHandler",[708,1291,1115],{"class":759},[708,1293,581],{"class":718},[708,1295,824],{"class":759},[708,1297,1298],{"class":710,"line":746},[708,1299,1300],{"class":759},"}\n",[698,1302,1304],{"className":944,"code":1303,"filename":946,"language":947,"meta":704,"style":704},"import io.stoatflow.core.exception.LogAndContinueDeserializationExceptionHandler;\n\nbuilder.streamsConfigOverrides(cfg ->\n    cfg.deserializationExceptionHandler(new LogAndContinueDeserializationExceptionHandler()));\n",[337,1305,1306,1330,1334,1350],{"__ignoreMap":704},[708,1307,1308,1310,1312,1314,1316,1318,1320,1322,1324,1326,1328],{"class":710,"line":711},[708,1309,715],{"class":714},[708,1311,956],{"class":759},[708,1313,352],{"class":763},[708,1315,961],{"class":759},[708,1317,352],{"class":763},[708,1319,966],{"class":759},[708,1321,352],{"class":763},[708,1323,971],{"class":759},[708,1325,352],{"class":763},[708,1327,581],{"class":759},[708,1329,978],{"class":763},[708,1331,1332],{"class":710,"line":722},[708,1333,750],{"emptyLinePlaceholder":749},[708,1335,1336,1339,1341,1343,1345,1347],{"class":710,"line":730},[708,1337,1338],{"class":1071},"builder",[708,1340,352],{"class":763},[708,1342,339],{"class":718},[708,1344,1115],{"class":763},[708,1346,1118],{"class":759},[708,1348,1349],{"class":763},"->\n",[708,1351,1352,1355,1357,1359,1361,1364,1367],{"class":710,"line":738},[708,1353,1354],{"class":1071},"    cfg",[708,1356,352],{"class":763},[708,1358,368],{"class":718},[708,1360,1115],{"class":763},[708,1362,1363],{"class":714},"new",[708,1365,1366],{"class":718}," LogAndContinueDeserializationExceptionHandler",[708,1368,1369],{"class":763},"()));\n",[320,1371,1372,1373,1376,1377,1380,1381,1376,1384,1386],{},"The DLQ handlers take optional flags: ",[337,1374,1375],{},"includeStackTrace"," (default ",[337,1378,1379],{},"true",") controls whether the full stack trace is written to a header, and the deserialization handler additionally takes ",[337,1382,1383],{},"includeOriginalHeaders",[337,1385,1379],{},") to copy the source record's headers onto the DLQ record under a prefix.",[403,1388,1390],{"id":1389},"configuring-a-handler-in-yaml","Configuring a handler in YAML",[320,1392,1393,1394,1396,1397,1400,1401,1404],{},"The ",[337,1395,680],{}," module can resolve handlers by ",[324,1398,1399],{},"fully qualified class name"," under ",[337,1402,1403],{},"stoatflow.*",". Builder overrides (above) take precedence over YAML; YAML takes precedence over the defaults.",[698,1406,1410],{"className":1407,"code":1408,"language":1409,"meta":704,"style":704},"language-yaml shiki shiki-themes vitesse-light","stoatflow:\n  application-id: my-app\n  bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS:-localhost:9092}\n\n  deserialization-exception-handler: io.stoatflow.core.exception.LogAndContinueDeserializationExceptionHandler\n  processing-exception-handler: io.stoatflow.core.exception.LogAndFailProcessingExceptionHandler\n  production-exception-handler: io.stoatflow.core.exception.DefaultProductionExceptionHandler\n","yaml",[337,1411,1412,1420,1431,1441,1445,1454,1464],{"__ignoreMap":704},[708,1413,1414,1417],{"class":710,"line":711},[708,1415,961],{"class":1416},"su6XF",[708,1418,1419],{"class":763},":\n",[708,1421,1422,1425,1428],{"class":710,"line":722},[708,1423,1424],{"class":1416},"  application-id",[708,1426,1427],{"class":763},":",[708,1429,1430],{"class":863}," my-app\n",[708,1432,1433,1436,1438],{"class":710,"line":730},[708,1434,1435],{"class":1416},"  bootstrap-servers",[708,1437,1427],{"class":763},[708,1439,1440],{"class":863}," ${KAFKA_BOOTSTRAP_SERVERS:-localhost:9092}\n",[708,1442,1443],{"class":710,"line":738},[708,1444,750],{"emptyLinePlaceholder":749},[708,1446,1447,1450,1452],{"class":710,"line":746},[708,1448,1449],{"class":1416},"  deserialization-exception-handler",[708,1451,1427],{"class":763},[708,1453,1274],{"class":863},[708,1455,1456,1459,1461],{"class":710,"line":753},[708,1457,1458],{"class":1416},"  processing-exception-handler",[708,1460,1427],{"class":763},[708,1462,1463],{"class":863}," io.stoatflow.core.exception.LogAndFailProcessingExceptionHandler\n",[708,1465,1466,1469,1471],{"class":710,"line":776},[708,1467,1468],{"class":1416},"  production-exception-handler",[708,1470,1427],{"class":763},[708,1472,727],{"class":863},[520,1474,1476],{"color":522,"icon":1475},"i-lucide-info",[320,1477,1478,1481,1482,1484,1485,1487,1488,1492],{},[324,1479,1480],{},"YAML can only configure handlers with a public no-arg constructor."," The DLQ handlers require a ",[337,1483,658],{}," constructor argument, so they cannot be set from YAML directly — configure them in code via ",[337,1486,339],{}," (above), or write a thin no-arg subclass that hard-codes the topic and reference ",[1489,1490,1491],"em",{},"that"," class from YAML. A class with no matching no-arg constructor fails at startup with a clear instantiation error.",[403,1494,1496],{"id":1495},"dlq-records-and-headers","DLQ records and headers",[320,1498,1499,1500,1503,1504,1506,1507,1510],{},"When a DLQ handler fires, it builds a ",[337,1501,1502],{},"ProducerRecord"," targeting your configured ",[337,1505,658],{}," and returns it to the engine. That record is ",[324,1508,1509],{},"sent through the same transactional producer as your normal output",", committed atomically on the next commit barrier — so a DLQ record exists if and only if the rest of that epoch committed. No separate producer, no lost-or-duplicated error records.",[320,1512,1513],{},"The original key and value bytes are preserved where available:",[357,1515,1516,1525,1534],{},[360,1517,1518,1520,1521,1524],{},[324,1519,437],{}," failures carry the ",[324,1522,1523],{},"raw source bytes"," verbatim (key and value), since deserialization never succeeded.",[360,1526,1527,1529,1530,1533],{},[324,1528,454],{}," failures serialize the in-flight key and value with ",[337,1531,1532],{},"toString().toByteArray()"," — the raw bytes are no longer available after the record was deserialized for processing.",[360,1535,1536,1538],{},[324,1537,474],{}," failures carry the (already-serialized) record bytes that failed to send.",[1540,1541,1543],"h3",{"id":1542},"header-reference","Header reference",[320,1545,1546,1547,1549,1550,1553],{},"All DLQ headers use the ",[337,1548,390],{}," namespace. The double-underscore prefix follows the Kafka convention for system headers, so DLQ tooling that filters ",[337,1551,1552],{},"__","-prefixed headers must opt in to surface these.",[408,1555,1556,1569],{},[411,1557,1558],{},[414,1559,1560,1563,1566],{},[417,1561,1562],{},"Header key",[417,1564,1565],{},"Present on",[417,1567,1568],{},"Value",[430,1570,1571,1593,1605,1617,1633,1645,1657,1669,1702,1715,1728,1740],{},[414,1572,1573,1578,1581],{},[435,1574,1575],{},[337,1576,1577],{},"__stoatflow.errors.type",[435,1579,1580],{},"all",[435,1582,1583,369,1586,1589,1590],{},[337,1584,1585],{},"DESERIALIZATION",[337,1587,1588],{},"PROCESSING",", or ",[337,1591,1592],{},"PRODUCTION",[414,1594,1595,1600,1602],{},[435,1596,1597],{},[337,1598,1599],{},"__stoatflow.errors.exception",[435,1601,1580],{},[435,1603,1604],{},"Exception class name",[414,1606,1607,1612,1614],{},[435,1608,1609],{},[337,1610,1611],{},"__stoatflow.errors.message",[435,1613,1580],{},[435,1615,1616],{},"Exception message",[414,1618,1619,1624,1630],{},[435,1620,1621],{},[337,1622,1623],{},"__stoatflow.errors.stacktrace",[435,1625,1626,1627,1629],{},"all (if ",[337,1628,1375],{},")",[435,1631,1632],{},"Full stack trace",[414,1634,1635,1640,1642],{},[435,1636,1637],{},[337,1638,1639],{},"__stoatflow.errors.topic",[435,1641,1580],{},[435,1643,1644],{},"Original source topic",[414,1646,1647,1652,1654],{},[435,1648,1649],{},[337,1650,1651],{},"__stoatflow.errors.partition",[435,1653,1580],{},[435,1655,1656],{},"Original source partition",[414,1658,1659,1664,1666],{},[435,1660,1661],{},[337,1662,1663],{},"__stoatflow.errors.offset",[435,1665,1580],{},[435,1667,1668],{},"Original source offset",[414,1670,1671,1676,1679],{},[435,1672,1673],{},[337,1674,1675],{},"__stoatflow.errors.component",[435,1677,1678],{},"deser, production",[435,1680,1681,1684,1685,1688,1689,1684,1692,1684,1695,1684,1698,1701],{},[337,1682,1683],{},"KEY"," \u002F ",[337,1686,1687],{},"VALUE"," (deser); ",[337,1690,1691],{},"KEY_SERIALIZATION",[337,1693,1694],{},"VALUE_SERIALIZATION",[337,1696,1697],{},"SEND",[337,1699,1700],{},"PARTITIONER"," (production)",[414,1703,1704,1709,1712],{},[435,1705,1706],{},[337,1707,1708],{},"__stoatflow.errors.processor",[435,1710,1711],{},"processing, production",[435,1713,1714],{},"Failing processor name; sink-node id on multi-sink topologies",[414,1716,1717,1722,1725],{},[435,1718,1719],{},[337,1720,1721],{},"__stoatflow.errors.timestamp",[435,1723,1724],{},"processing",[435,1726,1727],{},"Record timestamp",[414,1729,1730,1735,1737],{},[435,1731,1732],{},[337,1733,1734],{},"__stoatflow.errors.target.topic",[435,1736,334],{},[435,1738,1739],{},"The topic the record was being sent to",[414,1741,1742,1747,1752],{},[435,1743,1744],{},[337,1745,1746],{},"__stoatflow.errors.original.\u003Ckey>",[435,1748,1749,1750,1629],{},"deser (if ",[337,1751,1383],{},[435,1753,1754],{},"Each original source header, copied under this prefix",[320,1756,1757],{},"Inspect a DLQ record with the console consumer:",[698,1759,1763],{"className":1760,"code":1761,"language":1762,"meta":704,"style":704},"language-bash shiki shiki-themes vitesse-light","kafka-console-consumer.sh --bootstrap-server localhost:9092 \\\n  --topic my-app.deserialization-errors.dlq --from-beginning \\\n  --property print.headers=true --property print.key=true\n","bash",[337,1764,1765,1780,1793],{"__ignoreMap":704},[708,1766,1767,1770,1774,1777],{"class":710,"line":711},[708,1768,1769],{"class":718},"kafka-console-consumer.sh",[708,1771,1773],{"class":1772},"sEi1f"," --bootstrap-server",[708,1775,1776],{"class":863}," localhost:9092",[708,1778,1779],{"class":1772}," \\\n",[708,1781,1782,1785,1788,1791],{"class":710,"line":722},[708,1783,1784],{"class":1772},"  --topic",[708,1786,1787],{"class":863}," my-app.deserialization-errors.dlq",[708,1789,1790],{"class":1772}," --from-beginning",[708,1792,1779],{"class":1772},[708,1794,1795,1798,1801,1803,1806,1809],{"class":710,"line":730},[708,1796,1797],{"class":1772},"  --property",[708,1799,1800],{"class":863}," print.headers=",[708,1802,1379],{"class":714},[708,1804,1805],{"class":1772}," --property",[708,1807,1808],{"class":863}," print.key=",[708,1810,1811],{"class":714},"true\n",[403,1813,1815],{"id":1814},"production-error-classification","Production-error classification",[320,1817,1818,1819,1821,1822,1825,1826,1829,1830,1833,1834,1836,1837,1839],{},"The production stage distinguishes errors that are worth retrying from those that are not. ",[337,1820,486],{}," treats Kafka client ",[337,1823,1824],{},"RetriableException","s and ",[337,1827,1828],{},"TimeoutException"," (including when they appear as the ",[337,1831,1832],{},"cause",") as retriable and returns ",[337,1835,517],{},"; serialization errors and non-retriable send errors return ",[337,1838,506],{}," (routing to the DLQ first if a topic is configured).",[320,1841,1842],{},"Underneath, StoatFlow classifies producer exceptions into three categories that determine engine-level behaviour:",[408,1844,1845,1855],{},[411,1846,1847],{},[414,1848,1849,1852],{},[417,1850,1851],{},"Category",[417,1853,1854],{},"Meaning",[430,1856,1857,1867,1881],{},[414,1858,1859,1864],{},[435,1860,1861],{},[337,1862,1863],{},"FATAL",[435,1865,1866],{},"The engine cannot recover — triggers shutdown regardless of handler. Includes producer-fencing, authentication\u002Fauthorization, serialization, and broker-incompatibility errors.",[414,1868,1869,1874],{},[435,1870,1871],{},[337,1872,1873],{},"ABORTABLE",[435,1875,1876,1877,1880],{},"Routed to your ",[337,1878,1879],{},"productionExceptionHandler.handle(...)","; the handler's decision is respected.",[414,1882,1883,1888],{},[435,1884,1885],{},[337,1886,1887],{},"SUPPRESSED",[435,1889,1890,1891,1894],{},"Trace-logged only; a follow-up after a prior abort (e.g. ",[337,1892,1893],{},"TransactionAbortedException",").",[320,1896,1897,1898,1901,1902,1904],{},"Because StoatFlow runs as a ",[349,1899,1900],{"href":48},"single instance",", there is no task to migrate a fenced producer to — so producer-fencing and related errors that Kafka Streams would treat as recoverable task migrations are ",[337,1903,1863],{}," here. The application exits and a fresh process resumes from the last committed barrier.",[403,1906,1908],{"id":1907},"custom-handlers","Custom handlers",[320,1910,1911,1912,1915,1916,1919,1920,1923,1924,1927,1928,1931,1932,1935,1936,1684,1938,1940,1941,1943],{},"Implement the handler interface for the stage you want to control. The ",[337,1913,1914],{},"handle"," methods use the Kafka Streams-compatible parameter order ",[337,1917,1918],{},"(context, record, exception)",": the context is the KS-shaped ",[337,1921,1922],{},"ErrorHandlerContext",", and the record is the in-flight ",[337,1925,1926],{},"Record"," (processing), raw ",[337,1929,1930],{},"ConsumerRecord\u003CByteArray, ByteArray>"," (deserialization), or ",[337,1933,1934],{},"ProducerRecord\u003CByteArray?, ByteArray?>"," (production). A handler returns a response object combining the ",[337,1937,498],{},[337,1939,506],{}," decision with an optional list of DLQ ",[337,1942,1502],{},"s — the engine sends those transactionally for you.",[694,1945,1946,2104],{"group":696},[698,1947,1949],{"className":700,"code":1948,"filename":702,"language":703,"meta":704,"style":704},"import io.stoatflow.core.exception.ErrorHandlerContext\nimport io.stoatflow.core.exception.ProcessingExceptionHandler\nimport io.stoatflow.core.exception.ProcessingHandlerResponse\nimport io.stoatflow.core.processor.Record\n\nclass SkipNullPointerHandler : ProcessingExceptionHandler {\n    override fun handle(\n        context: ErrorHandlerContext,\n        record: Record\u003C*, *>,\n        exception: Exception,\n    ): ProcessingHandlerResponse =\n        if (exception is NullPointerException) {\n            ProcessingHandlerResponse.continueProcessing()\n        } else {\n            ProcessingHandlerResponse.fail()\n        }\n}\n",[337,1950,1951,1958,1965,1972,1979,1983,2000,2013,2022,2032,2042,2053,2067,2077,2087,2096,2100],{"__ignoreMap":704},[708,1952,1953,1955],{"class":710,"line":711},[708,1954,715],{"class":714},[708,1956,1957],{"class":718}," io.stoatflow.core.exception.ErrorHandlerContext\n",[708,1959,1960,1962],{"class":710,"line":722},[708,1961,715],{"class":714},[708,1963,1964],{"class":718}," io.stoatflow.core.exception.ProcessingExceptionHandler\n",[708,1966,1967,1969],{"class":710,"line":730},[708,1968,715],{"class":714},[708,1970,1971],{"class":718}," io.stoatflow.core.exception.ProcessingHandlerResponse\n",[708,1973,1974,1976],{"class":710,"line":738},[708,1975,715],{"class":714},[708,1977,1978],{"class":718}," io.stoatflow.core.processor.Record\n",[708,1980,1981],{"class":710,"line":746},[708,1982,750],{"emptyLinePlaceholder":749},[708,1984,1985,1988,1992,1995,1998],{"class":710,"line":753},[708,1986,1987],{"class":714},"class",[708,1989,1991],{"class":1990},"sUxyF"," SkipNullPointerHandler",[708,1993,1994],{"class":759}," : ",[708,1996,1997],{"class":1990},"ProcessingExceptionHandler",[708,1999,801],{"class":759},[708,2001,2002,2005,2008,2011],{"class":710,"line":776},[708,2003,2004],{"class":1067},"    override",[708,2006,2007],{"class":714}," fun",[708,2009,2010],{"class":718}," handle",[708,2012,773],{"class":759},[708,2014,2015,2018,2020],{"class":710,"line":793},[708,2016,2017],{"class":759},"        context: ",[708,2019,1922],{"class":1990},[708,2021,1097],{"class":759},[708,2023,2024,2027,2029],{"class":710,"line":804},[708,2025,2026],{"class":759},"        record: ",[708,2028,1926],{"class":1990},[708,2030,2031],{"class":759},"\u003C*, *>,\n",[708,2033,2034,2037,2040],{"class":710,"line":812},[708,2035,2036],{"class":759},"        exception: ",[708,2038,2039],{"class":1990},"Exception",[708,2041,1097],{"class":759},[708,2043,2044,2047,2050],{"class":710,"line":827},[708,2045,2046],{"class":759},"    ): ",[708,2048,2049],{"class":1990},"ProcessingHandlerResponse",[708,2051,2052],{"class":763}," =\n",[708,2054,2055,2058,2061,2064],{"class":710,"line":839},[708,2056,2057],{"class":714},"        if",[708,2059,2060],{"class":759}," (exception ",[708,2062,2063],{"class":714},"is",[708,2065,2066],{"class":759}," NullPointerException) {\n",[708,2068,2069,2072,2075],{"class":710,"line":844},[708,2070,2071],{"class":759},"            ProcessingHandlerResponse.",[708,2073,2074],{"class":718},"continueProcessing",[708,2076,931],{"class":759},[708,2078,2079,2082,2085],{"class":710,"line":852},[708,2080,2081],{"class":759},"        } ",[708,2083,2084],{"class":714},"else",[708,2086,801],{"class":759},[708,2088,2089,2091,2094],{"class":710,"line":870},[708,2090,2071],{"class":759},[708,2092,2093],{"class":718},"fail",[708,2095,931],{"class":759},[708,2097,2098],{"class":710,"line":876},[708,2099,907],{"class":759},[708,2101,2102],{"class":710,"line":884},[708,2103,1300],{"class":759},[698,2105,2107],{"className":944,"code":2106,"filename":946,"language":947,"meta":704,"style":704},"import io.stoatflow.core.exception.ErrorHandlerContext;\nimport io.stoatflow.core.exception.ProcessingExceptionHandler;\nimport io.stoatflow.core.exception.ProcessingHandlerResponse;\nimport io.stoatflow.core.processor.Record;\n\npublic class SkipNullPointerHandler implements ProcessingExceptionHandler {\n    @Override\n    public ProcessingHandlerResponse handle(\n            ErrorHandlerContext context, Record\u003C?, ?> record, Exception exception) {\n        if (exception instanceof NullPointerException) {\n            return ProcessingHandlerResponse.continueProcessing();\n        }\n        return ProcessingHandlerResponse.fail();\n    }\n}\n",[337,2108,2109,2133,2157,2181,2205,2209,2227,2235,2247,2289,2308,2322,2326,2339,2344],{"__ignoreMap":704},[708,2110,2111,2113,2115,2117,2119,2121,2123,2125,2127,2129,2131],{"class":710,"line":711},[708,2112,715],{"class":714},[708,2114,956],{"class":759},[708,2116,352],{"class":763},[708,2118,961],{"class":759},[708,2120,352],{"class":763},[708,2122,966],{"class":759},[708,2124,352],{"class":763},[708,2126,971],{"class":759},[708,2128,352],{"class":763},[708,2130,1922],{"class":759},[708,2132,978],{"class":763},[708,2134,2135,2137,2139,2141,2143,2145,2147,2149,2151,2153,2155],{"class":710,"line":722},[708,2136,715],{"class":714},[708,2138,956],{"class":759},[708,2140,352],{"class":763},[708,2142,961],{"class":759},[708,2144,352],{"class":763},[708,2146,966],{"class":759},[708,2148,352],{"class":763},[708,2150,971],{"class":759},[708,2152,352],{"class":763},[708,2154,1997],{"class":759},[708,2156,978],{"class":763},[708,2158,2159,2161,2163,2165,2167,2169,2171,2173,2175,2177,2179],{"class":710,"line":730},[708,2160,715],{"class":714},[708,2162,956],{"class":759},[708,2164,352],{"class":763},[708,2166,961],{"class":759},[708,2168,352],{"class":763},[708,2170,966],{"class":759},[708,2172,352],{"class":763},[708,2174,971],{"class":759},[708,2176,352],{"class":763},[708,2178,2049],{"class":759},[708,2180,978],{"class":763},[708,2182,2183,2185,2187,2189,2191,2193,2195,2197,2199,2201,2203],{"class":710,"line":738},[708,2184,715],{"class":714},[708,2186,956],{"class":759},[708,2188,352],{"class":763},[708,2190,961],{"class":759},[708,2192,352],{"class":763},[708,2194,966],{"class":759},[708,2196,352],{"class":763},[708,2198,330],{"class":759},[708,2200,352],{"class":763},[708,2202,1926],{"class":759},[708,2204,978],{"class":763},[708,2206,2207],{"class":710,"line":746},[708,2208,750],{"emptyLinePlaceholder":749},[708,2210,2211,2214,2217,2219,2222,2225],{"class":710,"line":753},[708,2212,2213],{"class":1067},"public",[708,2215,2216],{"class":1067}," class",[708,2218,1991],{"class":1990},[708,2220,2221],{"class":1067}," implements",[708,2223,2224],{"class":718}," ProcessingExceptionHandler",[708,2226,801],{"class":763},[708,2228,2229,2232],{"class":710,"line":776},[708,2230,2231],{"class":763},"    @",[708,2233,2234],{"class":1067},"Override\n",[708,2236,2237,2240,2243,2245],{"class":710,"line":793},[708,2238,2239],{"class":1067},"    public",[708,2241,2242],{"class":759}," ProcessingHandlerResponse ",[708,2244,1914],{"class":718},[708,2246,773],{"class":763},[708,2248,2249,2252,2255,2258,2261,2264,2267,2269,2272,2275,2278,2280,2283,2285,2287],{"class":710,"line":804},[708,2250,2251],{"class":759},"            ErrorHandlerContext ",[708,2253,2254],{"class":1071},"context",[708,2256,2257],{"class":763},",",[708,2259,2260],{"class":759}," Record",[708,2262,2263],{"class":763},"\u003C",[708,2265,2266],{"class":1067},"?",[708,2268,2257],{"class":763},[708,2270,2271],{"class":1067}," ?",[708,2273,2274],{"class":763},">",[708,2276,2277],{"class":1071}," record",[708,2279,2257],{"class":763},[708,2281,2282],{"class":759}," Exception ",[708,2284,971],{"class":1071},[708,2286,1629],{"class":763},[708,2288,801],{"class":763},[708,2290,2291,2293,2295,2298,2301,2304,2306],{"class":710,"line":812},[708,2292,2057],{"class":714},[708,2294,530],{"class":763},[708,2296,2297],{"class":759},"exception ",[708,2299,2300],{"class":1067},"instanceof",[708,2302,2303],{"class":759}," NullPointerException",[708,2305,1629],{"class":763},[708,2307,801],{"class":763},[708,2309,2310,2313,2316,2318,2320],{"class":710,"line":827},[708,2311,2312],{"class":714},"            return",[708,2314,2315],{"class":1071}," ProcessingHandlerResponse",[708,2317,352],{"class":763},[708,2319,2074],{"class":718},[708,2321,1247],{"class":763},[708,2323,2324],{"class":710,"line":839},[708,2325,907],{"class":763},[708,2327,2328,2331,2333,2335,2337],{"class":710,"line":844},[708,2329,2330],{"class":714},"        return",[708,2332,2315],{"class":1071},[708,2334,352],{"class":763},[708,2336,2093],{"class":718},[708,2338,1247],{"class":763},[708,2340,2341],{"class":710,"line":852},[708,2342,2343],{"class":763},"    }\n",[708,2345,2346],{"class":710,"line":870},[708,2347,1300],{"class":763},[320,2349,1393,2350,2352,2353,2355,2356,2359,2360,352],{},[337,2351,1922],{}," carries the source topic, partition, offset, timestamp, headers, failing processor node id, and the raw source key\u002Fvalue bytes, so your handler can log or tag DLQ records precisely. To emit a DLQ record from a custom handler, build a ",[337,2354,1934],{}," and pass it to ",[337,2357,2358],{},"continueProcessing(listOf(...))"," or ",[337,2361,2362],{},"fail(listOf(...))",[320,2364,2365],{},"A custom handler referenced from YAML must have a public no-arg constructor; one configured in code can take any constructor arguments you like.",[403,2367,2369],{"id":2368},"application-level-dlq-routing","Application-level DLQ routing",[320,2371,2372,2373,2376,2377,2380,2381,2384],{},"The exception handlers above catch ",[324,2374,2375],{},"failures"," — records that throw or fail to (de)serialize. For ",[324,2378,2379],{},"business-rule rejections"," (a record that deserializes fine but fails your validation), route it explicitly inside the topology with an ordinary sink. This is just normal DSL: branch the invalid records and ",[337,2382,2383],{},".to(...)"," a DLQ topic.",[694,2386,2387,2557],{"group":696},[698,2388,2390],{"className":700,"code":2389,"filename":702,"language":703,"meta":704,"style":704},"val validated = builder.stream\u003CString, Order>(\"orders\")\n\nvalidated\n    .filterNot({ _, order -> order.isValid() }, Named.`as`(\"invalid\"))\n    .to(\"orders.invalid.dlq\", Produced.`as`(\"dlq-sink\"))\n\nvalidated\n    .filter({ _, order -> order.isValid() }, Named.`as`(\"valid\"))\n    .mapValues({ order -> order.normalize() })\n    .to(\"orders.normalized\")\n",[337,2391,2392,2424,2428,2433,2466,2490,2494,2498,2524,2544],{"__ignoreMap":704},[708,2393,2394,2396,2399,2401,2404,2407,2409,2411,2413,2416,2419,2422],{"class":710,"line":711},[708,2395,756],{"class":714},[708,2397,2398],{"class":759}," validated ",[708,2400,764],{"class":763},[708,2402,2403],{"class":759}," builder.",[708,2405,2406],{"class":718},"stream",[708,2408,2263],{"class":759},[708,2410,821],{"class":1990},[708,2412,369],{"class":759},[708,2414,2415],{"class":1990},"Order",[708,2417,2418],{"class":759},">(",[708,2420,2421],{"class":863},"\"orders\"",[708,2423,919],{"class":759},[708,2425,2426],{"class":710,"line":722},[708,2427,750],{"emptyLinePlaceholder":749},[708,2429,2430],{"class":710,"line":730},[708,2431,2432],{"class":759},"validated\n",[708,2434,2435,2438,2441,2444,2446,2449,2452,2455,2458,2460,2463],{"class":710,"line":738},[708,2436,2437],{"class":759},"    .",[708,2439,2440],{"class":718},"filterNot",[708,2442,2443],{"class":759},"({ _, order ",[708,2445,1105],{"class":763},[708,2447,2448],{"class":759}," order.",[708,2450,2451],{"class":718},"isValid",[708,2453,2454],{"class":759},"() }, Named.",[708,2456,2457],{"class":718},"`as`",[708,2459,1115],{"class":759},[708,2461,2462],{"class":863},"\"invalid\"",[708,2464,2465],{"class":759},"))\n",[708,2467,2468,2470,2473,2475,2478,2481,2483,2485,2488],{"class":710,"line":746},[708,2469,2437],{"class":759},[708,2471,2472],{"class":718},"to",[708,2474,1115],{"class":759},[708,2476,2477],{"class":863},"\"orders.invalid.dlq\"",[708,2479,2480],{"class":759},", Produced.",[708,2482,2457],{"class":718},[708,2484,1115],{"class":759},[708,2486,2487],{"class":863},"\"dlq-sink\"",[708,2489,2465],{"class":759},[708,2491,2492],{"class":710,"line":753},[708,2493,750],{"emptyLinePlaceholder":749},[708,2495,2496],{"class":710,"line":776},[708,2497,2432],{"class":759},[708,2499,2500,2502,2505,2507,2509,2511,2513,2515,2517,2519,2522],{"class":710,"line":793},[708,2501,2437],{"class":759},[708,2503,2504],{"class":718},"filter",[708,2506,2443],{"class":759},[708,2508,1105],{"class":763},[708,2510,2448],{"class":759},[708,2512,2451],{"class":718},[708,2514,2454],{"class":759},[708,2516,2457],{"class":718},[708,2518,1115],{"class":759},[708,2520,2521],{"class":863},"\"valid\"",[708,2523,2465],{"class":759},[708,2525,2526,2528,2531,2534,2536,2538,2541],{"class":710,"line":804},[708,2527,2437],{"class":759},[708,2529,2530],{"class":718},"mapValues",[708,2532,2533],{"class":759},"({ order ",[708,2535,1105],{"class":763},[708,2537,2448],{"class":759},[708,2539,2540],{"class":718},"normalize",[708,2542,2543],{"class":759},"() })\n",[708,2545,2546,2548,2550,2552,2555],{"class":710,"line":812},[708,2547,2437],{"class":759},[708,2549,2472],{"class":718},[708,2551,1115],{"class":759},[708,2553,2554],{"class":863},"\"orders.normalized\"",[708,2556,919],{"class":759},[698,2558,2560],{"className":944,"code":2559,"filename":946,"language":947,"meta":704,"style":704},"KStream\u003CString, Order> validated = builder.stream(\"orders\");\n\nvalidated\n    .filterNot((k, order) -> order.isValid(), Named.as(\"invalid\"))\n    .to(\"orders.invalid.dlq\", Produced.as(\"dlq-sink\"));\n\nvalidated\n    .filter((k, order) -> order.isValid(), Named.as(\"valid\"))\n    .mapValues(Order::normalize)\n    .to(\"orders.normalized\");\n",[337,2561,2562,2600,2604,2608,2658,2693,2697,2701,2744,2760],{"__ignoreMap":704},[708,2563,2564,2567,2569,2571,2573,2576,2578,2581,2583,2585,2587,2589,2591,2593,2596,2598],{"class":710,"line":711},[708,2565,2566],{"class":759},"KStream",[708,2568,2263],{"class":763},[708,2570,821],{"class":1067},[708,2572,2257],{"class":763},[708,2574,2575],{"class":1067}," Order",[708,2577,2274],{"class":763},[708,2579,2580],{"class":1071}," validated",[708,2582,1075],{"class":763},[708,2584,1108],{"class":1071},[708,2586,352],{"class":763},[708,2588,2406],{"class":718},[708,2590,1115],{"class":763},[708,2592,1190],{"class":1189},[708,2594,2595],{"class":863},"orders",[708,2597,1190],{"class":1189},[708,2599,1236],{"class":763},[708,2601,2602],{"class":710,"line":722},[708,2603,750],{"emptyLinePlaceholder":749},[708,2605,2606],{"class":710,"line":730},[708,2607,2432],{"class":759},[708,2609,2610,2612,2614,2617,2620,2622,2625,2627,2630,2632,2634,2636,2639,2642,2644,2647,2649,2651,2654,2656],{"class":710,"line":738},[708,2611,2437],{"class":763},[708,2613,2440],{"class":718},[708,2615,2616],{"class":763},"((",[708,2618,2619],{"class":759},"k",[708,2621,2257],{"class":763},[708,2623,2624],{"class":759}," order",[708,2626,1629],{"class":763},[708,2628,2629],{"class":763}," ->",[708,2631,2624],{"class":1071},[708,2633,352],{"class":763},[708,2635,2451],{"class":718},[708,2637,2638],{"class":763},"(),",[708,2640,2641],{"class":1071}," Named",[708,2643,352],{"class":763},[708,2645,2646],{"class":718},"as",[708,2648,1115],{"class":763},[708,2650,1190],{"class":1189},[708,2652,2653],{"class":863},"invalid",[708,2655,1190],{"class":1189},[708,2657,2465],{"class":763},[708,2659,2660,2662,2664,2666,2668,2671,2673,2675,2678,2680,2682,2684,2686,2689,2691],{"class":710,"line":746},[708,2661,2437],{"class":763},[708,2663,2472],{"class":718},[708,2665,1115],{"class":763},[708,2667,1190],{"class":1189},[708,2669,2670],{"class":863},"orders.invalid.dlq",[708,2672,1190],{"class":1189},[708,2674,2257],{"class":763},[708,2676,2677],{"class":1071}," Produced",[708,2679,352],{"class":763},[708,2681,2646],{"class":718},[708,2683,1115],{"class":763},[708,2685,1190],{"class":1189},[708,2687,2688],{"class":863},"dlq-sink",[708,2690,1190],{"class":1189},[708,2692,1198],{"class":763},[708,2694,2695],{"class":710,"line":753},[708,2696,750],{"emptyLinePlaceholder":749},[708,2698,2699],{"class":710,"line":776},[708,2700,2432],{"class":759},[708,2702,2703,2705,2707,2709,2711,2713,2715,2717,2719,2721,2723,2725,2727,2729,2731,2733,2735,2737,2740,2742],{"class":710,"line":793},[708,2704,2437],{"class":763},[708,2706,2504],{"class":718},[708,2708,2616],{"class":763},[708,2710,2619],{"class":759},[708,2712,2257],{"class":763},[708,2714,2624],{"class":759},[708,2716,1629],{"class":763},[708,2718,2629],{"class":763},[708,2720,2624],{"class":1071},[708,2722,352],{"class":763},[708,2724,2451],{"class":718},[708,2726,2638],{"class":763},[708,2728,2641],{"class":1071},[708,2730,352],{"class":763},[708,2732,2646],{"class":718},[708,2734,1115],{"class":763},[708,2736,1190],{"class":1189},[708,2738,2739],{"class":863},"valid",[708,2741,1190],{"class":1189},[708,2743,2465],{"class":763},[708,2745,2746,2748,2750,2752,2754,2756,2758],{"class":710,"line":804},[708,2747,2437],{"class":763},[708,2749,2530],{"class":718},[708,2751,1115],{"class":763},[708,2753,2415],{"class":759},[708,2755,1092],{"class":714},[708,2757,2540],{"class":759},[708,2759,919],{"class":763},[708,2761,2762,2764,2766,2768,2770,2773,2775],{"class":710,"line":812},[708,2763,2437],{"class":763},[708,2765,2472],{"class":718},[708,2767,1115],{"class":763},[708,2769,1190],{"class":1189},[708,2771,2772],{"class":863},"orders.normalized",[708,2774,1190],{"class":1189},[708,2776,1236],{"class":763},[320,2778,2779,2780,2783],{},"This pattern gives you full control over the DLQ record shape (you choose the serde and payload) and is the right tool when \"this record is bad\" is a domain decision rather than an exception. The ",[337,2781,2782],{},"stock-tick-filter"," example app uses exactly this approach to send validation failures to a DLQ topic in Avro form.",[403,2785,2787],{"id":2786},"related","Related",[357,2789,2790,2795,2800,2805],{},[360,2791,2792,2794],{},[349,2793,351],{"href":78}," — the why behind the three stages, CONTINUE-vs-FAIL trade-offs, and transactional DLQ delivery.",[360,2796,2797,2799],{},[349,2798,1056],{"href":146}," — where deserialization failures originate, and how to make malformed data fail predictably.",[360,2801,2802,2804],{},[349,2803,67],{"href":68}," — late-record policies, which are configured separately from these exception handlers.",[360,2806,2807,2809,2810,2812],{},[349,2808,47],{"href":48}," — what a ",[337,2811,506],{}," decision does to the running process and how recovery works on restart.",[2814,2815,2816],"style",{},"html pre.shiki code .sbBg2, html code.shiki .sbBg2{--shiki-default:#1E754F}html pre.shiki code .sySUi, html code.shiki .sySUi{--shiki-default:#59873A}html pre.shiki code .suHK_, html code.shiki .suHK_{--shiki-default:#393A34}html pre.shiki code .sYZai, html code.shiki .sYZai{--shiki-default:#999999}html pre.shiki code .spphp, html code.shiki .spphp{--shiki-default:#B56959}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 pre.shiki code .si04Y, html code.shiki .si04Y{--shiki-default:#AB5959}html pre.shiki code .svycV, html code.shiki .svycV{--shiki-default:#B07D48}html pre.shiki code .sSP4y, html code.shiki .sSP4y{--shiki-default:#B5695977}html pre.shiki code .su6XF, html code.shiki .su6XF{--shiki-default:#998418}html pre.shiki code .sEi1f, html code.shiki .sEi1f{--shiki-default:#A65E2B}html pre.shiki code .sUxyF, html code.shiki .sUxyF{--shiki-default:#2E8F82}",{"title":704,"searchDepth":722,"depth":722,"links":2818},[2819,2820,2821,2822,2823,2826,2827,2828,2829],{"id":405,"depth":722,"text":406},{"id":537,"depth":722,"text":538},{"id":670,"depth":722,"text":671},{"id":1389,"depth":722,"text":1390},{"id":1495,"depth":722,"text":1496,"children":2824},[2825],{"id":1542,"depth":730,"text":1543},{"id":1814,"depth":722,"text":1815},{"id":1907,"depth":722,"text":1908},{"id":2368,"depth":722,"text":2369},{"id":2786,"depth":722,"text":2787},"Configure deserialization, processing, and production exception handlers — log-and-continue, log-and-fail, or dead-letter-queue — in code or YAML, and inspect the DLQ headers StoatFlow writes.","md",{},{"icon":98},"how-to",{"title":95,"description":2830},"Uu1g3-tfZMh2pu-L4U1fYM4_ggnZrKtRS1AdZ2gH1jU",[2838,2840],{"title":92,"path":88,"stem":89,"description":2839,"icon":93,"children":-1},"How to define a StoatFlow topology — StreamsBuilder, the KStream\u002FKTable abstractions, and the fan-out rule that reuses a KStream reference for multiple branches.",{"title":100,"path":101,"stem":102,"description":2841,"icon":103,"children":-1},"Use the Stores factory and Materialized to configure persistent and in-memory key-value, window, session, and versioned stores — and read them back via interactive queries.",1783713357345]