{"record":{"id":"72876f10d08f8146","repo":"cloudflare/cloudflared","slug":"stack-trace-s","errorCode":null,"errorMessage":"stack trace: %s","messagePattern":"stack trace: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"supervisor/tunnel.go","lineNumber":386,"sourceCode":"// on error returns a flag indicating if error can be retried\nfunc (e *EdgeTunnelServer) serveTunnel(\n\tctx context.Context,\n\tconnLog *ConnAwareLogger,\n\taddr *allregions.EdgeAddr,\n\tconnIndex uint8,\n\tfuse *booleanFuse,\n\tbackoff *protocolFallback,\n\tprotocol connection.Protocol,\n) (err error, recoverable bool) {\n\t// Treat panics as recoverable errors\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tvar ok bool\n\t\t\terr, ok = r.(error)\n\t\t\tif !ok {\n\t\t\t\terr = fmt.Errorf(\"ServeTunnel: %v\", r)\n\t\t\t}\n\t\t\terr = errors.Wrapf(err, \"stack trace: %s\", string(debug.Stack()))\n\t\t\trecoverable = true\n\t\t}\n\t}()\n\n\tdefer e.config.Observer.SendDisconnect(connIndex)\n\terr, recoverable = e.serveConnection(\n\t\tctx,\n\t\tconnLog,\n\t\taddr,\n\t\tconnIndex,\n\t\tfuse,\n\t\tbackoff,\n\t\tprotocol,\n\t)\n\n\tif err != nil {\n\t\tswitch err := err.(type) {\n\t\tcase connection.DupConnRegisterTunnelError:","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/supervisor/tunnel.go#L368-L404","documentation":"ServeTunnel wraps its work in a recover() handler so panics inside the tunnel serving loop do not crash the daemon. When a panic occurs, the recovered value is converted to an error and wrapped with the goroutine stack trace under the message 'stack trace: %s'; recoverable is set so the connection is re-established.","triggerScenarios":"Any panic inside serveConnection/handleTunnel: nil pointer dereference, index out of range, etc., while serving a tunnel connection on a specific connIndex.","commonSituations":"Race conditions corrupting shared state (e.g. unsynchronized *tls.Config mutation); unexpected nil fields from edge; bugs triggered by malformed edge messages.","solutions":["Read the wrapped stack trace in the error to locate the panicking frame","Update cloudflared — many panic bugs are fixed in newer releases","Look for concurrent mutation of shared config/state and add synchronization (mutex or Clone before mutate)","Report the stack trace to cloudflared issues if it reproduces"],"exampleFix":"// before\ncfg.CurvePreferences = curves // mutating shared *tls.Config -> data race/panic\n// after\ncfg = cfg.Clone()\ncfg.CurvePreferences = curves","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        err = fmt.Errorf(\"ServeTunnel: %v\", r)\n        err = errors.Wrapf(err, \"stack trace: %s\", string(debug.Stack()))\n        recoverable = true\n    }\n}()","preventionTips":["Never mutate shared *tls.Config or other state without Clone()/mutex","Run `go test -race` on modified packages","Keep cloudflared updated to pick up panic fixes","Ship panic stack traces with bug reports"],"tags":["panic","recovery","tunnel"],"backgroundTag":"internal-invariant-violation","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}