Skip to content

Commit b9a7ebf

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 f041695 commit b9a7ebf

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
@@ -730,7 +730,48 @@ func getIssueQueryTypeWithoutFieldValues(hasLabels bool, hasSince bool) issueQue
730730
}
731731
}
732732

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

2180-
// searchIssuesHandler runs the REST issues search, enriches each hit (best-effort) with custom
2181-
// field values fetched via a single follow-up GraphQL nodes() query, and applies any post-process
2182-
// options (e.g. IFC labelling).
2221+
// searchIssuesHandler runs the REST issues search, enriches each hit with custom field values
2222+
// fetched via a single follow-up GraphQL nodes() query, and applies any post-process options
2223+
// (e.g. IFC labelling).
21832224
func searchIssuesHandler(ctx context.Context, deps ToolDependencies, args map[string]any, mode searchMode, options ...searchOption) (*mcp.CallToolResult, error) {
21842225
const errorPrefix = "failed to search issues"
21852226

@@ -2206,18 +2247,21 @@ func searchIssuesHandler(ctx context.Context, deps ToolDependencies, args map[st
22062247
return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, errorPrefix, resp, body), nil
22072248
}
22082249

2209-
// The field value enrichment is best-effort: a failure here (e.g. a server whose
2210-
// GraphQL schema predates the issueFieldValues field) must never fail the search.
22112250
var fieldValuesByID map[string][]MinimalFieldValue
22122251
if len(result.Issues) > 0 {
22132252
gqlClient, err := deps.GetGQLClient(ctx)
22142253
if err != nil {
2215-
_, _ = ghErrors.NewGitHubGraphQLErrorToCtx(ctx, errorPrefix+": failed to get GitHub GraphQL client", err)
2216-
} else {
2217-
fieldValuesByID, err = fetchIssueFieldValuesByNodeID(ctx, gqlClient, result.Issues)
2218-
if err != nil {
2219-
_, _ = ghErrors.NewGitHubGraphQLErrorToCtx(ctx, errorPrefix+": failed to fetch issue field values", err)
2254+
return utils.NewToolResultErrorFromErr(errorPrefix+": failed to get GitHub GraphQL client", err), nil
2255+
}
2256+
fieldValuesByID, err = fetchIssueFieldValuesByNodeID(ctx, gqlClient, result.Issues)
2257+
if err != nil {
2258+
const enrichmentError = errorPrefix + ": failed to fetch issue field values"
2259+
if !isUnsupportedIssueFieldValuesSchemaError(err) {
2260+
return ghErrors.NewGitHubGraphQLErrorResponse(ctx, enrichmentError, err), nil
22202261
}
2262+
// Older GHES schemas can lack this optional enrichment. Preserve the REST
2263+
// search results while retaining the compatibility failure for observability.
2264+
_, _ = ghErrors.NewGitHubGraphQLErrorToCtx(ctx, enrichmentError, err)
22212265
}
22222266
}
22232267

0 commit comments

Comments
 (0)