Skip to content

Commit c64b6fe

Browse files
fix(issues): narrow search field enrichment fallback
Only tolerate GraphQL schema validation failures that show the optional Issue.issueFieldValues selection or its known fragments are unsupported. Surface client, auth, rate-limit, network, resolver, malformed response, and unrelated GraphQL failures. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent ee37dd8 commit c64b6fe

2 files changed

Lines changed: 251 additions & 124 deletions

File tree

pkg/github/issues.go

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,48 @@ func getIssueQueryTypeWithoutFieldValues(hasLabels bool, hasSince bool) issueQue
733733
}
734734
}
735735

736+
func isUnsupportedIssueFieldValuesSchemaError(err error) bool {
737+
if err == nil {
738+
return false
739+
}
740+
741+
message := strings.ToLower(err.Error())
742+
mentionsIssueType := strings.Contains(message, "on type 'issue'") ||
743+
strings.Contains(message, `on type "issue"`) ||
744+
strings.Contains(message, "on type issue")
745+
if strings.Contains(message, "issuefieldvalues") &&
746+
mentionsIssueType &&
747+
(strings.Contains(message, "doesn't exist on type") ||
748+
strings.Contains(message, "does not exist on type") ||
749+
strings.Contains(message, "cannot query field") ||
750+
strings.Contains(message, "is not defined on type")) {
751+
return true
752+
}
753+
754+
issueFieldTypes := [...]string{
755+
"issuefielddate",
756+
"issuefieldnumber",
757+
"issuefieldsingleselect",
758+
"issuefieldtext",
759+
}
760+
for _, issueFieldType := range issueFieldTypes {
761+
if !strings.Contains(message, issueFieldType) {
762+
continue
763+
}
764+
return strings.Contains(message, "unknown type") ||
765+
strings.Contains(message, "isn't a defined type") ||
766+
strings.Contains(message, "is not a defined type") ||
767+
strings.Contains(message, "fragment cannot be spread") ||
768+
strings.Contains(message, "can never be of type")
769+
}
770+
return false
771+
}
772+
736773
func isUnsupportedListIssuesIssueFieldsError(err error) bool {
774+
if isUnsupportedIssueFieldValuesSchemaError(err) {
775+
return true
776+
}
777+
737778
message := err.Error()
738779
if strings.Contains(message, "IssueFieldValueFilter") {
739780
return true
@@ -2180,9 +2221,9 @@ func fetchIssueReadEnrichment(ctx context.Context, gqlClient *githubv4.Client, n
21802221
return enrichment, nil
21812222
}
21822223

2183-
// searchIssuesHandler runs the REST issues search, enriches each hit (best-effort) with custom
2184-
// field values fetched via a single follow-up GraphQL nodes() query, and applies any post-process
2185-
// options (e.g. IFC labelling).
2224+
// searchIssuesHandler runs the REST issues search, enriches each hit with custom field values
2225+
// fetched via a single follow-up GraphQL nodes() query, and applies any post-process options
2226+
// (e.g. IFC labelling).
21862227
func searchIssuesHandler(ctx context.Context, deps ToolDependencies, args map[string]any, mode searchMode, options ...searchOption) (*mcp.CallToolResult, error) {
21872228
const errorPrefix = "failed to search issues"
21882229

@@ -2209,18 +2250,21 @@ func searchIssuesHandler(ctx context.Context, deps ToolDependencies, args map[st
22092250
return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, errorPrefix, resp, body), nil
22102251
}
22112252

2212-
// The field value enrichment is best-effort: a failure here (e.g. a server whose
2213-
// GraphQL schema predates the issueFieldValues field) must never fail the search.
22142253
var fieldValuesByID map[string][]MinimalFieldValue
22152254
if len(result.Issues) > 0 {
22162255
gqlClient, err := deps.GetGQLClient(ctx)
22172256
if err != nil {
2218-
_, _ = ghErrors.NewGitHubGraphQLErrorToCtx(ctx, errorPrefix+": failed to get GitHub GraphQL client", err)
2219-
} else {
2220-
fieldValuesByID, err = fetchIssueFieldValuesByNodeID(ctx, gqlClient, result.Issues)
2221-
if err != nil {
2222-
_, _ = ghErrors.NewGitHubGraphQLErrorToCtx(ctx, errorPrefix+": failed to fetch issue field values", err)
2257+
return utils.NewToolResultErrorFromErr(errorPrefix+": failed to get GitHub GraphQL client", err), nil
2258+
}
2259+
fieldValuesByID, err = fetchIssueFieldValuesByNodeID(ctx, gqlClient, result.Issues)
2260+
if err != nil {
2261+
const enrichmentError = errorPrefix + ": failed to fetch issue field values"
2262+
if !isUnsupportedIssueFieldValuesSchemaError(err) {
2263+
return ghErrors.NewGitHubGraphQLErrorResponse(ctx, enrichmentError, err), nil
22232264
}
2265+
// Older GHES schemas can lack this optional enrichment. Preserve the REST
2266+
// search results while retaining the compatibility failure for observability.
2267+
_, _ = ghErrors.NewGitHubGraphQLErrorToCtx(ctx, enrichmentError, err)
22242268
}
22252269
}
22262270

0 commit comments

Comments
 (0)