{"record":{"id":"ac95be3f9eb45e2d","repo":"golang/go","slug":"profile-missing-function-start-line-data-go-versi","errorCode":null,"errorMessage":"profile missing Function.start_line data (Go version of profiled application too old? Go 1.20+ automatically adds this to profiles)","messagePattern":"profile missing Function\\.start_line data \\(Go version of profiled application too old\\? Go 1\\.20\\+ automatically adds this to profiles\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/internal/pgo/pprof.go","lineNumber":106,"sourceCode":"\t\t// Create the key to the nodeMapKey.\n\t\tnamedEdge := NamedCallEdge{\n\t\t\tCallerName:     canonicalName,\n\t\t\tCallSiteOffset: n.Info.Lineno - n.Info.StartLine,\n\t\t}\n\n\t\tfor _, e := range n.Out {\n\t\t\ttotalWeight += e.WeightValue()\n\t\t\tnamedEdge.CalleeName = e.Dest.Info.Name\n\t\t\t// Create new entry or increment existing entry.\n\t\t\tweight[namedEdge] += e.WeightValue()\n\t\t}\n\t}\n\n\tif !seenStartLine {\n\t\t// TODO(prattmic): If Function.start_line is missing we could\n\t\t// fall back to using absolute line numbers, which is better\n\t\t// than nothing.\n\t\treturn NamedEdgeMap{}, 0, fmt.Errorf(\"profile missing Function.start_line data (Go version of profiled application too old? Go 1.20+ automatically adds this to profiles)\")\n\t}\n\treturn postProcessNamedEdgeMap(weight, totalWeight)\n}\n\nfunc sortByWeight(edges []NamedCallEdge, weight map[NamedCallEdge]int64) {\n\tsort.Slice(edges, func(i, j int) bool {\n\t\tei, ej := edges[i], edges[j]\n\t\tif wi, wj := weight[ei], weight[ej]; wi != wj {\n\t\t\treturn wi > wj // want larger weight first\n\t\t}\n\t\t// same weight, order by name/line number\n\t\tif ei.CallerName != ej.CallerName {\n\t\t\treturn ei.CallerName < ej.CallerName\n\t\t}\n\t\tif ei.CalleeName != ej.CalleeName {\n\t\t\treturn ei.CalleeName < ej.CalleeName\n\t\t}\n\t\treturn ei.CallSiteOffset < ej.CallSiteOffset","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/internal/pgo/pprof.go#L88-L124","documentation":"Thrown when the pprof profile's Function entries lack start_line information (seenStartLine is false after iterating all graph nodes). The PGO inliner needs relative line numbers derived from Function.start_line to compute call-site offsets. Go 1.20+ automatically includes start_line in emitted profiles; older versions do not, making them incompatible with PGO. The error message itself suggests this cause.","triggerScenarios":"After building the profile graph and iterating all nodes' Out edges, no Function.Info has a non-zero start_line, so seenStartLine remains false. This happens when the profiled binary was built with Go < 1.20, which doesn't populate Function.start_line in the pprof metadata.","commonSituations":"Profiling an application built with Go 1.19 or earlier, then attempting to use that profile for PGO (which requires Go 1.21+). Also possible with profiles from non-Go applications or stripped binaries where symbol/debug info is incomplete.","solutions":["Rebuild the profiled application with Go 1.20 or later, then re-collect the CPU profile.","Ensure the binary was not stripped of debug info (-ldflags='-s -w' removes symbols; avoid this for profiling builds).","Verify the Go version used to build the profiled binary: `go version <binary>`.","Confirm the pprof profile has Function.start_line by inspecting it with `go tool pprof -proto <file> | grep start_line`."],"exampleFix":"// Rebuild with Go 1.20+:\n// go1.21 build -o myapp .\n// ./myapp  # run representative workload\n// (profile collected with runtime/pprof or SIGUSR1)\n// go build -pgo=cpu.prof","handlingStrategy":"validation","validationCode":"// Check Go version of the binary that produced the profile:\nfunc checkGoVersionForPGO(binaryPath string) error {\n    out, err := exec.Command(\"go\", \"version\", binaryPath).CombinedOutput()\n    if err != nil { return err }\n    s := string(out)\n    // Must be go1.20+\n    if !strings.Contains(s, \"go1.2\") && !strings.Contains(s, \"go1.3\") {\n        return fmt.Errorf(\"binary built with %s; PGO requires Go 1.20+ for start_line\", s)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always build the profiled binary with Go 1.20 or later.","Do not strip debug symbols (-s -w) from binaries used for profiling.","Verify Function.start_line presence with `go tool pprof -proto <file>` before PGO build."],"tags":["pgo","pprof","version-mismatch","start-line","go-compiler-internal"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}