{"record":{"id":"936cf69a63228692","repo":"go-delve/delve","slug":"expression-q-is-unreadable-v-936cf6","errorCode":null,"errorMessage":"Expression %q is unreadable: %v","messagePattern":"Expression %q is unreadable: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/eval.go","lineNumber":635,"sourceCode":"//     containing a single pointer field) the type conversion to \"interface {}\"\n//     is performed.\n//   - If srcv and dstv have the same type and are both addressable then the\n//     contents of srcv are copied byte-by-byte into dstv\nfunc (scope *EvalScope) setValue(dstv, srcv *Variable, srcExpr string) error {\n\tsrcv.loadValue(loadSingleValue)\n\n\ttyperr := srcv.isType(dstv.RealType, dstv.Kind)\n\tif _, isTypeConvErr := typerr.(*typeConvErr); isTypeConvErr {\n\t\t// attempt iface -> eface and ptr-shaped -> eface conversions.\n\t\treturn convertToEface(srcv, dstv)\n\t}\n\tif typerr != nil {\n\t\treturn typerr\n\t}\n\n\tif srcv.Unreadable != nil {\n\t\t//lint:ignore ST1005 backwards compatibility\n\t\treturn fmt.Errorf(\"Expression %q is unreadable: %v\", srcExpr, srcv.Unreadable)\n\t}\n\n\t// Numerical types\n\tswitch dstv.Kind {\n\tcase reflect.Float32, reflect.Float64:\n\t\tf, _ := constant.Float64Val(srcv.Value)\n\t\treturn dstv.writeFloatRaw(f, dstv.RealType.Size())\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\tn, _ := constant.Int64Val(srcv.Value)\n\t\treturn dstv.writeUint(uint64(n), dstv.RealType.Size())\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\tn, _ := constant.Uint64Val(srcv.Value)\n\t\treturn dstv.writeUint(n, dstv.RealType.Size())\n\tcase reflect.Bool:\n\t\treturn dstv.writeBool(constant.BoolVal(srcv.Value))\n\tcase reflect.Complex64, reflect.Complex128:\n\t\treal, _ := constant.Float64Val(constant.Real(srcv.Value))\n\t\timag, _ := constant.Float64Val(constant.Imag(srcv.Value))","sourceCodeStart":617,"sourceCodeEnd":653,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/eval.go#L617-L653","documentation":"setValue (used both for SetVariable and for copying arguments during function-call injection via funcCallCopyOneArg) refuses to write when the source expression evaluated to an unreadable variable — srcv.Unreadable was set while loading it (bad memory, optimized-out value, unreadable DWARF, etc.). The debugger surfaces the underlying unreadability reason rather than writing garbage to the destination.","triggerScenarios":"Calling SetVariable(name, value) or a function-call injection argument copy where the value expression resolves to a variable whose memory cannot be read (srcv.Unreadable != nil after loadValue), e.g. assigning one variable's value to another when the source variable is optimized out or lives in unreadable memory.","commonSituations":"Assigning from a variable that the compiler optimized into registers and DWARF cannot reconstruct; copying from a variable behind a nil or dangling pointer; source expression in an inlined frame whose location is unavailable; stripped/optimized binaries (-gcflags='-N -l' not used).","solutions":["Verify the source expression evaluates on its own first (EvalExpression); fix or replace it if it is unreadable.","Use a literal value instead of copying from an unreadable variable (e.g. x = 0 instead of x = y when y is unreadable).","Rebuild the debuggee without optimizations (-gcflags=\"all=-N -l\") so variables have concrete locations.","Evaluate in a different frame where the variable is actually live and addressable."],"exampleFix":"// before\ndbg.SetVariable(\"x\", \"optimizedOutVar\") // Expression \"optimizedOutVar\" is unreadable\n// after\nval, err := dbg.EvalExpression(\"optimizedOutVar\", cfg)\nif err == nil && val.Unreadable == nil {\n    dbg.SetVariable(\"x\", \"optimizedOutVar\")\n} else {\n    dbg.SetVariable(\"x\", \"0\")\n}","handlingStrategy":"validation","validationCode":"val, err := scope.EvalExpression(srcExpr, loadSingleValue)\nif err != nil || val == nil || val.Unreadable != nil {\n    return fmt.Errorf(\"source expression %q not readable, refusing assignment\", srcExpr)\n}","typeGuard":"func isReadable(v *proc.Variable) bool { return v != nil && v.Unreadable == nil }","tryCatchPattern":"if err := scope.SetVariable(name, value); err != nil {\n    var uv *proc.Variable\n    if strings.Contains(err.Error(), \"is unreadable\") {\n        // fall back to a literal assignment or surface the reason to the user\n        return fmt.Errorf(\"cannot copy from %s: %w\", value, err)\n    }\n    return err\n}","preventionTips":["Evaluate the source expression standalone before using it as an assignment source","Build without optimizations (-gcflags=\"all=-N -l\") so variables stay readable","Prefer literal values over variable-to-variable copies in automation scripts","Check Variable.Unreadable on any variable before using it as a value source"],"tags":["go","debugger","set-variable","unreadable-variable"],"backgroundTag":"variable-unreadable","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}