go-delve/delve · error

can not assign to function expression

Error message

can not assign to function expression

What it means

setValue's assignment path rejects targets whose real type is reflect.Func: function values are not assignable memory in Go, so delve refuses. If the target variable has a name it reports 'can not assign to <name>'; an anonymous/intermediate function-typed expression yields this generic message. Thrown during SetVariable and during function-call argument copying (funcCallCopyOneArg).

Source

Thrown at pkg/proc/eval.go:660

		return dstv.writeFloatRaw(f, dstv.RealType.Size())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n, _ := constant.Int64Val(srcv.Value)
		return dstv.writeUint(uint64(n), dstv.RealType.Size())
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		n, _ := constant.Uint64Val(srcv.Value)
		return dstv.writeUint(n, dstv.RealType.Size())
	case reflect.Bool:
		return dstv.writeBool(constant.BoolVal(srcv.Value))
	case reflect.Complex64, reflect.Complex128:
		real, _ := constant.Float64Val(constant.Real(srcv.Value))
		imag, _ := constant.Float64Val(constant.Imag(srcv.Value))
		return dstv.writeComplex(real, imag, dstv.RealType.Size())
	case reflect.Func:
		if dstv.RealType.Size() == 0 {
			if dstv.Name != "" {
				return fmt.Errorf("can not assign to %s", dstv.Name)
			}
			return errors.New("can not assign to function expression")
		}
	}

	// nilling nillable variables
	if srcv == nilVariable {
		return dstv.writeZero()
	}

	if srcv.Kind == reflect.String {
		if srcv.Base == 0 && srcv.Len > 0 && srcv.Flags&VariableConstant != 0 {
			return errFuncCallNotAllowedStrAlloc
		}
		return dstv.writeString(uint64(srcv.Len), srcv.Base)
	}

	// slice assignment (this is not handled by the writeCopy below so that
	// results of a reslice operation can be used here).
	if srcv.Kind == reflect.Slice {

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Do not assign func values; instead set an interface/bool flag the program checks, or use a breakpoint with a condition to alter control flow.
  2. Pass a pointer or an index/enum value the callee can dispatch on, instead of the function itself.
  3. If the goal is calling a function, use delve's function injection with non-func arguments only.
  4. Validate the target variable's Kind before issuing set: if Kind == reflect.Func, surface a friendly error in your tooling.

Example fix

// before
dbg.SetVariable("handler", "myHandler") // handler is func
// after
// set a flag or interface field instead:
dbg.SetVariable("useHandlerV2", "true")
Defensive patterns

Strategy: validation

Validate before calling

v, err := scope.EvalExpression(targetExpr, cfg)
if err == nil && v.Kind == reflect.Func {
    return fmt.Errorf("%s is a function and cannot be assigned", targetExpr)
}

Type guard

func isAssignable(v *proc.Variable) bool {
    return v != nil && v.Kind != reflect.Func
}

Try / catch

err := scope.SetValue(target, srcv)
if err != nil && strings.Contains(err.Error(), "can not assign") {
    return fmt.Errorf("delve cannot assign function values; mutate a flag/interface instead")
}

Prevention

When it happens

Trigger: Attempting `set f = someFunc` where f is a func; passing a function value as an argument to an injected function call (funcCallCopyOneArg) via EvalExpressionWithCalls; assigning to an expression that resolves to a func type.

Common situations: Trying to monkey-patch a callback/handler variable in a debug session; injecting a call like replaceHandler(myFunc) where the parameter is a func; RPC clients building SetVariable commands on function-typed fields.

Related errors


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/c4b30931dfd13ea1. Report an issue: GitHub.