Repository navigation
fix/search: print partial results when there are graphql errors - #1384
Draft
marcleblanc2 wants to merge 1 commit into
Draft
marcleblanc2 wants to merge 1 commit into
marcleblanc2 wants to merge 1 commit into
Conversation
src search discarded every result and exited non-zero when the GraphQL response carried errors for individual results, such as "repository does not exist" on one result's file.content. Treat errors that arrive alongside results as warnings (printed to stderr, in full with -v) and only fail hard when no results came back, matching the behaviour src repos list got in #1282. Fixes #1150 Amp-Thread-ID: https://ampcode.com/threads/T-01a18b53-40bb-7118-975d-9c1b224f5602 Co-authored-by: Amp <[email protected]>
marcleblanc2
marked this pull request as draft
October 30, 2026 06:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Relates to #1150
Problem
src searchdiscards every result and exits non-zero whenever the GraphQL response carrieserrors.request.Doininternal/apireturnsGraphQlErrorsand drops the data as soon as anerrorsarray is present. #1282 fixed the same class of problem forsrc repos listby switching toDoRawand treating errors-alongside-data as warnings; this PR applies the same treatment tosrc search.Change
cmd/src/search.go: the GraphQL call moves intorunSearch, which usesDoRaw. Errors that arrive alongside results are returned as warnings; errors with no results are still a hard error. The handler prints results as before, and printswarning: N errors during search; rerun with -v to inspect themto stderr (full path + message + raw JSON with-v). JSON output on stdout stays clean.cmd/src/repos_list.go:formatRepositoryListWarningsbecomesformatGraphQLWarnings(activity, warnings)so both commands share it.cmd/src/search_test.go:TestRunSearchHandlesGraphQLErrorscovers one result'sfile.contenterroring with the other results kept, and the no-results case (hard error).CHANGELOG.mdentry under Unreleased / Fixed.Why this does not fix #1150 yet
The reporter's error is on
search.results.results[309].file.content. Every hop from that field up tosearchis non-null in the schema:Sourcegraph's graphql-go fork implements spec null propagation (
internal/exec/exec.go): an error on a non-null field nulls its parent, and so on up to the first nullable ancestor. Here that issearch, so the server returnsdata.search: nulland the 300+ good results are never sent. Confirmed against a 8.1 instance by forcing an error under aFileMatch(badhighlight(...)arguments):{"data": {"search": null, "site": {"buildVersion": "..."}}, "errors": [{"message": "...", "path": ["search", "results", "results", 0, "file", "highlight"]}]}With this PR,
runSearchsees zero results plus errors and returns the hard error: same outcome as before. #1282 works forrepos listonly becauseRepository.defaultBranchhappens to be nullable, so a failure there nulls one field instead of the whole list.Root cause
src searchrequests the fullcontentof every matching file. The only consumer in the CLI is structural-search highlighting in text mode (searchHighlightMatch/applyHighlightsForFile);-jsonpasses it through. That per-result gitserver read is what fails when a repository disappears between the Zoekt index and the content fetch. The web app does not hit this because it uses streaming search, which never fetches content.Options
contentfrom the query unless the query containspatterntype:structural. Small change, removes the failure mode, and makes every search much lighter on the instance. Cost:file.contentdisappears from-jsonoutput for non-structural searches, which is a contract change (the reporter was using it).content, then one aliased batch query (r0: repository(name: ...) { commit(rev: ...) { blob(path: ...) { content } } },r1: ...) for the matched files.Query.repositoryis nullable, so a missing repository nulls only its own alias, and the partial-data handling in this PR has something to keep. Preserves the JSON contract; costs a second round trip. Recommended.content: String!→String).Other callers with the same data-plus-errors pattern
Checked every
.Do(caller incmd/andinternal/. The pattern only matters where a nullable boundary sits between the failing field and the data we want:src repos get: sameRepositoryFieldsfragment and nullabledefaultBranchasrepos list. A repository with an unresolvable HEAD returns everything else and the CLI throws it away. Same fix as fix/repo-list: print partial data when there are graphql errors #1282.src batchResolveWorkspacesForBatchSpec:repository.defaultBranch { target { oid } },defaultBranchnullable. One unresolvable repository drops all workspaces. Arguably should still fail, but a warning naming the repository is better than the raw error dump.users list,orgs list,users prune,extsvc list,search-jobs *,codeowners *, mutations: Postgres-backed fields only, no per-node calls to gitserver or code hosts. Leave as is.src lsphover / definitions / references: single-result queries; partial data is just null.src snapshot summary,internal/instancehealth:site: Site!,externalServices: ...!,permissionsSyncJobs: ...!are non-null, so any error nulls all ofdata. Cannot be fixed client-side. Separately,instancehealthstill queriessite.monitoringStatistics, which was removed from the schema in sourcegraph/sourcegraph@a83a00798bb (Dec 2024), so that query fails validation on 6.x+ instances. Separate bug.A more general alternative: change
request.Doto always unmarshaldataeven whenerrorsis present, returningGraphQlErrorsalongside. Callers thatreturn errkeep their current behaviour; callers that want partial data stop short-circuiting. Would have made #1282 and this PR a few lines each.Verification
go test ./...passes.FileMatchresults plus therepository does not existerror from the issue (the shape a server would send without null propagation): before (origin/main)GraphQL errors: {...}, exit 1, no results; after, both results in-jsonon stdout, exit 0,warning: 1 errors during search; rerun with -v to inspect themon stderr, full path/message/JSON with-v.count:2000unchanged, exit 0, no warnings. All repositories on that instance are cloned, so the reporter's race could not be reproduced there; the null-propagation behaviour above was confirmed instead with the forcedhighlighterror.