{"record":{"id":"a636b766475911c1","repo":"cockroachdb/cockroach","slug":"could-not-parse-query-expected-pkg-test-s","errorCode":null,"errorMessage":"could not parse query (expected PKG.TEST): %s","messagePattern":"could not parse query \\(expected PKG\\.TEST\\): (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/cmd/testowner/testowner.go","lineNumber":168,"sourceCode":"\t\t\twriteOwners(stdout, teams)\n\t\t\tfor _, log := range logs {\n\t\t\t\tfmt.Fprintln(stderr, log)\n\t\t\t}\n\t\t} else {\n\t\t\tfmt.Fprintf(stderr, \"usage: `testowner PKG.TEST` or `testowner` (with queries in stdin); got %d arguments, expected 0-1\\n\", len(flag.Args()))\n\t\t\treturn 1\n\t\t}\n\t}\n\treturn 0\n}\n\nfunc parseQuery(pkgAndTest string) (pkg string, test string) {\n\tconst githubPrefix = \"github.com/cockroachdb/cockroach/\"\n\tvar dotIdx int\n\tif strings.HasPrefix(pkgAndTest, githubPrefix) {\n\t\tdotIdx = strings.IndexByte(pkgAndTest[len(githubPrefix):], '.')\n\t\tif dotIdx <= 0 {\n\t\t\tpanic(fmt.Sprintf(\"could not parse query (expected PKG.TEST): %s\", pkgAndTest))\n\t\t}\n\t\tdotIdx += len(githubPrefix)\n\t} else {\n\t\tdotIdx = strings.IndexByte(pkgAndTest, '.')\n\t\tif dotIdx <= 0 {\n\t\t\tpanic(fmt.Sprintf(\"could not parse query (expected PKG.TEST): %s\", pkgAndTest))\n\t\t}\n\t}\n\tpkg, test = pkgAndTest[:dotIdx], pkgAndTest[dotIdx+1:]\n\treturn\n}\n\nfunc writeOwners(w io.Writer, teams []team.Team) {\n\tvar prev bool\n\tif len(teams) == 0 {\n\t\tpanic(\"empty team slice\")\n\t}\n\tfor _, team := range teams {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/cockroachdb/cockroach/blob/8812064a015d2faf99d3fc7e15880f94042954b0/pkg/cmd/testowner/testowner.go#L150-L186","documentation":"Raised by parseQuery (testowner.go:162-169) in its github-prefixed branch. The query began with `github.com/cockroachdb/cockroach/`, but strings.IndexByte found no '.' after that prefix (dotIdx == -1) or found one immediately after it (dotIdx == 0, i.e. an empty package), so the string cannot be split at the first post-prefix dot into a package and a test name. The tool signals this by panicking, so the process dies with a stack trace and non-zero exit. Both the single-argument mode (line 148) and each stdin line (line 137) run through this parse.","triggerScenarios":"Invoking `testowner github.com/cockroachdb/cockroach/pkg/cmd/dev` (package import path with the .TEST part forgotten); any github-prefixed string with no '.' after the prefix, e.g. `github.com/cockroachdb/cockroach/`; an empty package like `github.com/cockroachdb/cockroach/.TestFoo`; feeding stdin a list of package paths (from go list ./... or editor copy) instead of PKG.TEST lines.","commonSituations":"Pasting a package path from go-to-definition / go list output and forgetting to append .TestName; scripts that emit import paths rather than PKG.TEST pairs; a query truncated by shell history editing or a missing test name in a generated input file.","solutions":["Append the test name to form a full query: `testowner github.com/cockroachdb/cockroach/pkg/cmd/dev.TestDataDriven`","Or use the equivalent short form without the prefix: `testowner pkg/cmd/dev.TestDataDriven`","If piping many queries on stdin, generate `PKG.TEST` pairs (e.g. `go test -list '.*' ./pkg/...` output joined with the package) rather than bare package paths","Filter out blank/whitespace-only lines before feeding stdin (a prefix-only line cannot contain the .TEST part)"],"exampleFix":"// before: package import path only, no .TEST suffix after the github prefix\n$ ./testowner github.com/cockroachdb/cockroach/pkg/cmd/dev\npanic: could not parse query (expected PKG.TEST): github.com/cockroachdb/cockroach/pkg/cmd/dev\n\n// after: full github.com/.../PKG.TEST (or the short form)\n$ ./testowner github.com/cockroachdb/cockroach/pkg/cmd/dev.TestDataDriven\n$ ./testowner pkg/cmd/dev.TestDataDriven","handlingStrategy":"validation","validationCode":"// Mirrors parseQuery (testowner.go:162-179) without panicking: split at the\n// first '.' after the optional github.com/cockroachdb/cockroach/ prefix.\nfunc validateQuery(q string) error {\n\tconst prefix = \"github.com/cockroachdb/cockroach/\"\n\ts := strings.TrimPrefix(q, prefix)\n\tif dot := strings.IndexByte(s, '.'); dot <= 0 {\n\t\treturn fmt.Errorf(\"query must be PKG.TEST (got %q)\", q)\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"If you cannot pre-validate (e.g. calling the binary), catch the panic at the process boundary: a non-zero exit with `could not parse query` on stderr means malformed input — log the offending query and continue or abort. If you reuse parseQuery in-process, wrap the call with a deferred recover: `defer func() { if r := recover(); r != nil { /* handle bad query */ } }()`.","preventionTips":["Always type queries as full PKG.TEST, e.g. github.com/cockroachdb/cockroach/pkg/cmd/dev.TestDataDriven","Prefer the short form pkg/cmd/dev.TestDataDriven — fewer characters, no prefix to mistype","Generate stdin input as PKG.TEST pairs (join go list ./... with go test -list output), never bare import paths","Run validateQuery over each line before piping a batch to testowner"],"tags":["go","cli","input-validation","cockroachdb","test-ownership","string-parsing"],"backgroundTag":null,"analyzedSha":"8812064a015d2faf99d3fc7e15880f94042954b0","analyzedAt":"2026-08-15T16:34:17.351Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}