go-delve/delve · error

not an executable file

Error message

not an executable file

What it means

ErrNotExecutable is the sentinel error returned by the debugger when Delve is asked to launch a file that cannot be debugged because it is not a valid executable (wrong format, not compiled, or lacking execute permission). Tests like TestDebugger_LaunchNoMain and TestDebugger_LaunchInvalidFormat assert on it.

Source

Thrown at service/api/types.go:18

package api

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"unicode"
	"unicode/utf8"

	"github.com/go-delve/delve/pkg/proc"
)

// ErrNotExecutable is an error returned when trying
// to debug a non-executable file.
var ErrNotExecutable = errors.New("not an executable file")

// DebuggerState represents the current context of the debugger.
type DebuggerState struct {
	// PID of the process we are debugging.
	Pid int
	// Command line of the process we are debugging.
	TargetCommandLine string
	// Running is true if the process is running and no other information can be collected.
	Running bool
	// Recording is true if the process is currently being recorded and no other
	// information can be collected. While the debugger is in this state
	// sending a StopRecording request will halt the recording, every other
	// request will block until the process has been recorded.
	Recording bool
	// Core dumping currently in progress.
	CoreDumping bool
	// CurrentThread is the currently selected debugger thread.
	CurrentThread *Thread `json:"currentThread,omitempty"`

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Build the target first (go build) and pass the resulting binary to `dlv exec`
  2. chmod +x the file if it merely lacks the execute bit
  3. Verify the binary matches the host GOOS/GOARCH and contains Go symbols
  4. Use `dlv debug`/`dlv test` to let Delve compile the program itself

Example fix

// before
{ "request": "launch", "mode": "exec", "program": "./main.go" }
// after
{ "request": "launch", "mode": "exec", "program": "./bin/app" }
Defensive patterns

Strategy: try-catch

Validate before calling

info, err := os.Stat(program)
if err != nil || info.IsDir() || info.Mode()&0o111 == 0 {
	// not launchable as exec; build or chmod first
}

Try / catch

st, err := dbg.Execute(...)
if errors.Is(err, api.ErrNotExecutable) {
	// build the binary or fix permissions, then retry
}

Prevention

When it happens

Trigger: `debugger.Execute`/launch with a path pointing to a script, object file, core file, or non-Go binary; a binary compiled without a main package; a file with mode bits lacking +x.

Common situations: Pointing launch config `program` at a package directory's source file instead of the built binary; running `dlv exec` on a stripped/foreign-architecture binary; CI artifacts built without execute permissions.

Related errors


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