{"record":{"id":"733a2eadb50224a6","repo":"golang/go","slug":"s-pkgconfig-requires-perblock-perfunc-value","errorCode":null,"errorMessage":"%s: pkgconfig requires perblock/perfunc value","messagePattern":"(.+?): pkgconfig requires perblock/perfunc value","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/cover/cover.go","lineNumber":230,"sourceCode":"\t}\n\treturn strings.Split(strings.TrimSpace(string(data)), \"\\n\"), nil\n}\n\nfunc readPackageConfig(path string) error {\n\tdata, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error reading pkgconfig file %q: %v\", path, err)\n\t}\n\tif err := json.Unmarshal(data, &pkgconfig); err != nil {\n\t\treturn fmt.Errorf(\"error reading pkgconfig file %q: %v\", path, err)\n\t}\n\tswitch pkgconfig.Granularity {\n\tcase \"perblock\":\n\t\tcgran = coverage.CtrGranularityPerBlock\n\tcase \"perfunc\":\n\t\tcgran = coverage.CtrGranularityPerFunc\n\tdefault:\n\t\treturn fmt.Errorf(`%s: pkgconfig requires perblock/perfunc value`, path)\n\t}\n\treturn nil\n}\n\n// Block represents the information about a basic block to be recorded in the analysis.\n// Note: Our definition of basic block is based on control structures; we don't break\n// apart && and ||. We could but it doesn't seem important enough to bother.\ntype Block struct {\n\tstartByte token.Pos\n\tendByte   token.Pos\n\tnumStmt   int\n}\n\n// Package holds package-specific state.\ntype Package struct {\n\tmdb            *encodemeta.CoverageMetaDataBuilder\n\tcounterLengths []int\n}","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/cover/cover.go#L212-L248","documentation":"Thrown by 'go tool cover' readPackageConfig when the JSON config's Granularity field is neither 'perblock' nor 'perfunc'. Granularity selects whether coverage counters are emitted per basic block or per function; any other (or missing) value is rejected after unmarshalling succeeds.","triggerScenarios":"A -pkgcfg JSON with \"Granularity\": \"\" or \"Granularity\": \"perStmt\" or the field omitted entirely (zero value \"\").","commonSituations":"Schema skew between go versions (the field was added in a specific release). Hand-written config omitting the field. A tool generating the config with the wrong enum string.","solutions":["Set Granularity to exactly \"perblock\" or \"perfunc\" in the pkgcfg JSON","Regenerate the config with a go version matching the cover tool","If building coverage tooling, default to \"perblock\" unless you specifically want per-function granularity"],"exampleFix":"// before\n{ \"PkgPath\": \"p\", \"Granularity\": \"perStmt\" }\n// after\n{ \"PkgPath\": \"p\", \"Granularity\": \"perblock\" }","handlingStrategy":"validation","validationCode":"# Validate the Granularity field before invoking cover\npython3 -c \"import json; g=json.load(open('$PKGCFG'))['Granularity']; assert g in ('perblock','perfunc'), g\" || { echo \"bad Granularity\" >&2; exit 2; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default Granularity to perblock unless per-function is intended","Regenerate config when upgrading Go versions"],"tags":["go-toolchain","cover","pkgcfg","enum","validation"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T11:17:21.771Z"}