golang/go · error

preprocessed profile malformed header; got %q want %q

Error message

preprocessed profile malformed header; got %q want %q

What it means

FromSerialized read the first line successfully but it does not equal serializationHeader. The stream therefore starts with content that is not a serialized PGO profile — most often a raw pprof or a plain text profile passed to the wrong parser.

Source

Thrown at src/cmd/internal/pgo/deserialize.go:45

	return string(hdr) == serializationHeader, nil
}

// FromSerialized parses a profile from serialization output of Profile.WriteTo.
func FromSerialized(r io.Reader) (*Profile, error) {
	d := emptyProfile()

	scanner := bufio.NewScanner(r)
	scanner.Split(bufio.ScanLines)

	if !scanner.Scan() {
		if err := scanner.Err(); err != nil {
			return nil, fmt.Errorf("error reading preprocessed profile: %w", err)
		}
		return nil, fmt.Errorf("preprocessed profile missing header")
	}
	if gotHdr := scanner.Text() + "\n"; gotHdr != serializationHeader {
		return nil, fmt.Errorf("preprocessed profile malformed header; got %q want %q", gotHdr, serializationHeader)
	}

	for scanner.Scan() {
		readStr := scanner.Text()

		callerName := readStr

		if !scanner.Scan() {
			if err := scanner.Err(); err != nil {
				return nil, fmt.Errorf("error reading preprocessed profile: %w", err)
			}
			return nil, fmt.Errorf("preprocessed profile entry missing callee")
		}
		calleeName := scanner.Text()

		if !scanner.Scan() {
			if err := scanner.Err(); err != nil {
				return nil, fmt.Errorf("error reading preprocessed profile: %w", err)

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Feed FromSerialized only profiles written by Profile.WriteTo (the serialized format).
  2. For raw pprof files, use the appropriate pprof parser, not FromSerialized.
  3. Call IsSerialized first to confirm the format before parsing.

Example fix

// before: raw pprof fed to the serialized parser
prof, err := pgo.FromSerialized(file)

// after: confirm format first
if ok, _ := pgo.IsSerialized(bufReader); !ok {
    return errors.New("not a serialized PGO profile; parse as pprof instead")
}
prof, err := pgo.FromSerialized(bufReader)
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the serialized header before parsing.
// ok, err := pgo.IsSerialized(bufReader)
// if err != nil { return err }
// if !ok { return errors.New("not a serialized PGO profile; use the pprof parser instead") }

Try / catch

// prof, err := pgo.FromSerialized(r)
// if err != nil && strings.Contains(err.Error(), "malformed header") {
//     // wrong format (e.g. raw pprof); route to the correct parser
//     return err
// }

Prevention

When it happens

Trigger: First line of the reader, after appending a newline, differs from serializationHeader.

Common situations: User passes a raw pprof file (protobuf) to FromSerialized instead of a profile produced by Profile.WriteTo, or passes a textual CPU profile from an unrelated tool.

Understand the failure class

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/bbe6d0516b11642e. Report an issue: GitHub.