golang/go · error
wrong magic, not a Go object file
Error message
wrong magic, not a Go object file
What it means
Thrown by (*goobj.Header).Read when the first bytes of a file do not equal the gc object-file magic constant ("\x00go120ld"). The goobj package reads the export data / object index of files emitted by the gc compiler's object writer, and the magic both identifies the format and pins the on-disk version. Any byte mismatch (truncation, wrong format, version skew) aborts the parse before any block offsets are read.
Source
Thrown at src/cmd/internal/goobj/objfile.go:233
Offsets [NBlk]uint32
}
const Magic = "\x00go120ld"
func (h *Header) Write(w *Writer) {
w.RawString(h.Magic)
w.Bytes(h.Fingerprint[:])
w.Uint32(h.Flags)
for _, x := range h.Offsets {
w.Uint32(x)
}
}
func (h *Header) Read(r *Reader) error {
b := r.BytesAt(0, len(Magic))
h.Magic = string(b)
if h.Magic != Magic {
return errors.New("wrong magic, not a Go object file")
}
off := uint32(len(h.Magic))
copy(h.Fingerprint[:], r.BytesAt(off, len(h.Fingerprint)))
off += 8
h.Flags = r.uint32At(off)
off += 4
for i := range h.Offsets {
h.Offsets[i] = r.uint32At(off)
off += 4
}
return nil
}
func (h *Header) Size() int {
return len(h.Magic) + len(h.Fingerprint) + 4 + 4*len(h.Offsets)
}
// AutolibView on GitHub (pinned to b6b368adc5)
Solutions
- Verify the file is actually a gc object file: `go tool nm FILE` or `head -c8 FILE | xxd` and check it begins with the magic byte 0x00 followed by 'go120ld'.
- Rebuild the object with the toolchain version that matches the goobj reader (clean the build cache: `go clean -cache`).
- Confirm the path passed to goobj.Parse is the compiled object, not the source, archive wrapper, or linked executable.
- If consuming third-party objects, ensure they were produced by gc (this package does not read gccgo/GoLLVM objects).
Example fix
// before: feeding an arbitrary file to the goobj reader
f, _ := os.Open(path)
r := goobj.NewReader(f, ...)
hdr.Read(r) // -> "wrong magic, not a Go object file"
// after: sniff the magic before parsing so the caller gets a clear signal
const Magic = "\x00go120ld"
head := make([]byte, len(Magic))
if _, err := io.ReadFull(f, head); err != nil || string(head) != Magic {
return fmt.Errorf("%s: not a gc object file", path)
}
f.Seek(0, io.SeekStart)
hdr.Read(r) Defensive patterns
Strategy: validation
Validate before calling
// Validate the file is a gc object before handing it to goobj.
func isGcObject(path string) bool {
f, err := os.Open(path)
if err != nil { return false }
defer f.Close()
head := make([]byte, 8) // len(goobj.Magic)
if _, err := io.ReadFull(f, head); err != nil { return false }
return string(head) == "\x00go120ld"
} Type guard
// Narrow on the goobj.Read error after the fact.
func isWrongMagic(err error) bool {
return err != nil && strings.Contains(err.Error(), "wrong magic")
} Try / catch
if err := hdr.Read(r); err != nil {
if strings.Contains(err.Error(), "wrong magic") {
return fmt.Errorf("%s is not a gc object file: %w", path, err)
}
return err
} Prevention
- Sniff the 8-byte magic before parsing to fail fast with a clear message.
- Pin the Go toolchain version in CI (go.mod's `go` directive / toolchain) so object formats match.
- Run `go clean -cache` after toolchain upgrades to purge incompatible cached objects.
When it happens
Trigger: Calling goobj.Parse or (*Reader) on a path whose content is not a gc '.o' object: a source file, an archive unpacked wrong, a PE/ELF executable, or an object produced by a different/newer Go whose Magic constant changed. Also fires on a zero-length or truncated file where BytesAt returns fewer than len(Magic) bytes that do not match.
Common situations: Mixing Go toolchain versions (the magic string is bumped, e.g. go120ld, across major object-format revisions), feeding a text/source file to a loader that expects an object file, or a corrupted build cache / partial write left by a killed compiler process. Often seen in CI after a Go upgrade without rebuilding dependencies.
Related errors
- no DWARF data in go object file
- non-file URL
- file URL missing path
- file URL specifies non-local host
- file URL encodes volume in host field: too few slashes?
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/fcd72e64f2626acc.
Report an issue: GitHub.