{"record":{"id":"8b113f70c6ad21b1","repo":"go-delve/delve","slug":"terminated","errorCode":null,"errorMessage":"terminated","messagePattern":"terminated","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/dap/server.go","lineNumber":3403,"sourceCode":"\tloadCfg := s.loadConfig()\n\tloadCfg.MaxStringLen = maxStringLenInCallRetVars\n\n\t// TODO(polina): since call will resume execution of all goroutines,\n\t// we should do this asynchronously and send a continued event to the\n\t// editor, followed by a stop event when the call completes.\n\tstate, err := s.debugger.Command(&api.DebuggerCommand{\n\t\tName:                 api.Call,\n\t\tReturnInfoLoadConfig: api.LoadConfigFromProc(&loadCfg),\n\t\tExpr:                 expr,\n\t\tUnsafeCall:           false,\n\t\tGoroutineID:          int64(goid),\n\t\tWithEvents:           true,\n\t}, nil, s.conn.closedChan, s.convertDebuggerEvent)\n\tif processExited(state, err) {\n\t\ts.preTerminatedWG.Wait()\n\t\ts.sendExitedEvent(state, err)\n\t\ts.send(&dap.TerminatedEvent{Event: *s.newEvent(\"terminated\")})\n\t\treturn nil, nil, errors.New(\"terminated\")\n\t}\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// After the call is done, the goroutine where we injected the call should\n\t// return to the original stopped line with return values. However,\n\t// it is not guaranteed to be selected due to the possibility of the\n\t// of simultaneous breakpoints. Therefore, we check all threads.\n\tvar retVars []*proc.Variable\n\tfound := false\n\tfor _, t := range state.Threads {\n\t\tif t.GoroutineID == stateBeforeCall.SelectedGoroutine.ID &&\n\t\t\tt.Line == stateBeforeCall.SelectedGoroutine.CurrentLoc.Line && t.CallReturn {\n\t\t\tfound = true\n\t\t\t// The call completed. Get the return values.\n\t\t\tretVars, err = s.debugger.FindThreadReturnValues(t.ID, loadCfg)\n\t\t\tif err != nil {","sourceCodeStart":3385,"sourceCodeEnd":3421,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/service/dap/server.go#L3385-L3421","documentation":"During injected function-call evaluation, if the process exits (or terminates) while the call is in progress, the session detects it via processExited(state, err), emits exited/terminated events to the client, and then returns the sentinel error 'terminated' to the evaluate caller. It signals that the call never completed because the debuggee died.","triggerScenarios":"The injected call causes the target process to exit (e.g. calling os.Exit or a function that panics fatally); the debuggee is killed externally during a call; the program finishes/naturally exits while a call is being injected at the end of main.","commonSituations":"Evaluating calls like os.Exit(1) or log.Fatal from the debug console; long-running call racing with program termination at the last breakpoint in main; crashes triggered by the injected call's side effects.","solutions":["Do not evaluate calls that terminate the process (os.Exit, log.Fatal, panic)","Re-launch the debuggee; the session is over once the process exits","If calls near the end of main keep terminating, place breakpoints earlier or guard with runtime checks","Inspect the call's side effects in a sandbox/test instead of evaluating them in the live target"],"exampleFix":"// before (debug console, terminates target)\nos.Exit(1)\n// after\nfmt.Println(\"would exit\")  // or set a breakpoint instead of calling exit","handlingStrategy":"try-catch","validationCode":"// pre-screen dangerous calls before injecting\nblocked := []string{\"os.Exit\", \"log.Fatal\", \"panic\"}\nfor _, b := range blocked {\n    if strings.HasPrefix(expr, b) { return fmt.Errorf(\"refusing %q\", b) }\n}","typeGuard":null,"tryCatchPattern":"if err.Error() == \"terminated\" {\n    // the debuggee exited: tear down the session and relaunch before any further requests\n}","preventionTips":["Never evaluate process-terminating calls from the debug console","Avoid injected calls near program exit points","Treat a 'terminated' result as final — re-launch to continue debugging"],"tags":["dap","function-call","process-exit","go"],"backgroundTag":"process-terminated-during-call","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}