go-delve/delve · error

can't write halfway through a file

Error message

can't write halfway through a file

What it means

elfwriter.New panics with "can't write halfway through a file" when the underlying io.WriteSeeker's current position is not 0. The writer emits a complete ELF image from scratch (ELF header at offset 0) and only supports writing to a fresh, empty destination. This is an API-contract violation by the caller, so the library fails fast.

Source

Thrown at pkg/elfwriter/writer.go:51

	seekShstrndx      int64
}

type Note struct {
	Type elf.NType
	Name string
	Data []byte
}

// New creates a new Writer.
func New(w WriteCloserSeeker, fhdr *elf.FileHeader) *Writer {
	const (
		ehsize    = 64
		phentsize = 56
		shentsize = 64
	)

	if seek, _ := w.Seek(0, io.SeekCurrent); seek != 0 {
		panic("can't write halfway through a file")
	}

	r := &Writer{w: w}

	if fhdr.Class != elf.ELFCLASS64 {
		panic("unsupported")
	}

	if fhdr.Data != elf.ELFDATA2LSB {
		panic("unsupported")
	}

	// e_ident
	r.Write([]byte{0x7f, 'E', 'L', 'F', byte(fhdr.Class), byte(fhdr.Data), byte(fhdr.Version), byte(fhdr.OSABI), fhdr.ABIVersion, 0, 0, 0, 0, 0, 0, 0})

	r.u16(uint16(fhdr.Type))    // e_type
	r.u16(uint16(fhdr.Machine)) // e_machine
	r.u32(uint32(fhdr.Version)) // e_version

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Pass a fresh/empty WriteSeeker (new file truncated to 0, new bytes.Buffer).
  2. If reusing an existing file, call Seek(0, io.SeekStart) and Truncate(0) before New.
  3. If reusing a buffer, reset it (buf.Reset()) first.
  4. Wrap New in recover() if input origin cannot be trusted.

Example fix

// before
f, _ := os.Create("out.elf")
f.WriteString("junk")
w := elfwriter.New(f) // panics
// after
f, _ := os.Create("out.elf") // O_TRUNC, position 0
w := elfwriter.New(f)
Defensive patterns

Strategy: validation

Validate before calling

// Go: ensure the destination is fresh and at offset 0
if seek, _ := w.Seek(0, io.SeekCurrent); seek != 0 {
	return errors.New("writer must start at offset 0; use a fresh/truncated writer")
}

Prevention

When it happens

Trigger: Calling elfwriter.New with a WriteSeeker that has already been written to or whose cursor was Seek'ed to a non-zero offset — e.g. appending to an existing file or reusing a buffer after a previous New call.

Common situations: Reusing an os.File opened with O_APPEND or already containing data; calling New twice on the same bytes.Buffer that retains prior writes; building a core-dump copy after partially writing a header.

Related errors


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