{"record":{"id":"7c06a04d76759fb5","repo":"go-delve/delve","slug":"cannot-use-s-as-argument-s-in-function-s-stack","errorCode":null,"errorMessage":"cannot use %s as argument %s in function %s: stack object passed to escaping pointer: %s","messagePattern":"cannot use (.+?) as argument (.+?) in function (.+?): stack object passed to escaping pointer: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/fncall.go","lineNumber":576,"sourceCode":"\t}\n\n\treturn nil\n}\n\ntype funcCallArg struct {\n\tname       string\n\ttyp        godwarf.Type\n\toff        int64\n\tdwarfEntry *godwarf.Tree // non-nil if Go 1.17+\n\tisret      bool\n}\n\nfunc funcCallCopyOneArg(scope *EvalScope, fncall *functionCallState, actualArg *Variable, formalArg *funcCallArg, thread Thread) error {\n\tif scope.callCtx.checkEscape {\n\t\t//TODO(aarzilli): only apply the escapeCheck to leaking parameters.\n\t\terr := allPointers(actualArg, formalArg.name, func(addr uint64, name string) error {\n\t\t\tif !pointerEscapes(addr, scope.g.stack, scope.callCtx.stacks) {\n\t\t\t\treturn fmt.Errorf(\"cannot use %s as argument %s in function %s: stack object passed to escaping pointer: %s\", actualArg.Name, formalArg.name, fncall.fn.Name, name)\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t//TODO(aarzilli): automatic wrapping in interfaces for cases not handled\n\t// by convertToEface.\n\n\tformalScope, err := GoroutineScope(scope.target, thread)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar formalArgVar *Variable\n\tif formalArg.dwarfEntry != nil {","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/fncall.go#L558-L594","documentation":"During call injection Delve can run an escape check on each actual argument when scope.callCtx.checkEscape is enabled. If any pointer inside the argument points to an object on the goroutine's own stack that does not escape into any of the recorded stacks, passing it to the callee would be unsafe (the callee may retain it past the frame), so this error aborts the call.","triggerScenarios":"Calling a function with an argument containing a pointer to a stack-allocated local while checkEscape is on, and pointerEscapes finds the address only in the current goroutine stack, not in scope.callCtx.stacks.","commonSituations":"Calling helper functions with &local variables or structs containing pointers to stack temporaries; common when the callee actually leaks the pointer (Go compiler would normally heap-allocate it).","solutions":["Heap-allocate the value explicitly before the call, e.g. x := new(T) or a global","Assign the local to an interface/global so the compiler escapes it","Disable the escape check if you understand the aliasing risk (checkEscape in callCtx)"],"exampleFix":"// before\nlocal := MyStruct{}\ncall Process(&local) // stack object passed to escaping pointer\n// after\nlocal := new(MyStruct)\ncall Process(local)","handlingStrategy":"validation","validationCode":"// allocate arguments on the heap before the call\narg := new(MyStruct)\n*arg = value\n// then: call Process(arg)","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"stack object passed to escaping pointer\") {\n    // redo the call with a heap-allocated argument\n}","preventionTips":["Use new()/globals for arguments containing pointers when injecting calls","Avoid passing &local or values pointing into the current stack frame"],"tags":["go","debugger","escape-analysis","call-injection"],"backgroundTag":"stack-object-escape","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}