mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-02-14 09:05:04 -05:00
fix(dataplex): Capture GCP HTTP errors in MCP Toolbox (#2347)
### Description fix: Surface Dataplex API errors in MCP results This change addresses issue https://github.com/googleapis/genai-toolbox/issues/2203, where Dataplex API errors, such as '403 Forbidden' (Permission Denied), were not being properly surfaced in the MCP tool results. Previously, these critical API errors would manifest as generic "connection interrupted" messages, significantly hindering developer debugging and trust in the Toolbox. The fix enhances the error handling within the 'dataplexsearchentries' and 'dataplexsearchaspecttypes' tools. When an error occurs during the iteration of Dataplex API results, the system now: Utilizes 'google.golang.org/grpc/status.FromError' to attempt to convert the returned error into a gRPC status. This is crucial because Google Cloud client libraries often return errors compatible with gRPC. If the error is a gRPC status, the canonical error code (e.g., 'codes.PermissionDenied') and the associated error message are extracted. This ensures that users receive clear actionable error feedback, allowing for quicker diagnosis and resolution of issues like missing IAM permissions. This aligns with best practices for API error surfacing, improving the usability and reliability of the Dataplex tools within the GenAI Toolbox. Fixes https://github.com/googleapis/genai-toolbox/issues/2203 ## PR Checklist > Thank you for opening a Pull Request! Before submitting your PR, there are a > few things you can do to make sure it goes smoothly: - [ ] Make sure you reviewed [CONTRIBUTING.md](https://github.com/googleapis/genai-toolbox/blob/main/CONTRIBUTING.md) - [ ] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/genai-toolbox/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) - [ ] Make sure to add `!` if this involve a breaking change 🛠️ Fixes #<issue_number_goes_here> --------- Co-authored-by: Wenxin Du <117315983+duwenxin99@users.noreply.github.com> Co-authored-by: Averi Kitsch <akitsch@google.com>
This commit is contained in:
1
.github/workflows/link_checker_workflow.yaml
vendored
1
.github/workflows/link_checker_workflow.yaml
vendored
@@ -39,6 +39,7 @@ jobs:
|
|||||||
--no-progress
|
--no-progress
|
||||||
--cache
|
--cache
|
||||||
--max-cache-age 1d
|
--max-cache-age 1d
|
||||||
|
--exclude '^neo4j\+.*' --exclude '^bolt://.*'
|
||||||
README.md
|
README.md
|
||||||
docs/
|
docs/
|
||||||
output: /tmp/foo.txt
|
output: /tmp/foo.txt
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -63,6 +63,7 @@ require (
|
|||||||
google.golang.org/api v0.256.0
|
google.golang.org/api v0.256.0
|
||||||
google.golang.org/genai v1.37.0
|
google.golang.org/genai v1.37.0
|
||||||
google.golang.org/genproto v0.0.0-20251022142026-3a174f9686a8
|
google.golang.org/genproto v0.0.0-20251022142026-3a174f9686a8
|
||||||
|
google.golang.org/grpc v1.76.0
|
||||||
google.golang.org/protobuf v1.36.10
|
google.golang.org/protobuf v1.36.10
|
||||||
modernc.org/sqlite v1.40.0
|
modernc.org/sqlite v1.40.0
|
||||||
)
|
)
|
||||||
@@ -229,7 +230,6 @@ require (
|
|||||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 // indirect
|
||||||
google.golang.org/grpc v1.76.0 // indirect
|
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
modernc.org/libc v1.66.10 // indirect
|
modernc.org/libc v1.66.10 // indirect
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/util"
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
|
"google.golang.org/api/iterator"
|
||||||
"google.golang.org/api/option"
|
"google.golang.org/api/option"
|
||||||
|
grpcstatus "google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SourceKind string = "dataplex"
|
const SourceKind string = "dataplex"
|
||||||
@@ -173,9 +175,18 @@ func (s *Source) SearchAspectTypes(ctx context.Context, query string, pageSize i
|
|||||||
var results []*dataplexpb.AspectType
|
var results []*dataplexpb.AspectType
|
||||||
for {
|
for {
|
||||||
entry, err := it.Next()
|
entry, err := it.Next()
|
||||||
if err != nil {
|
|
||||||
|
if err == iterator.Done {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
if st, ok := grpcstatus.FromError(err); ok {
|
||||||
|
errorCode := st.Code()
|
||||||
|
errorMessage := st.Message()
|
||||||
|
return nil, fmt.Errorf("failed to search aspect types with error code: %q message: %s", errorCode.String(), errorMessage)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("failed to search aspect types: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Create an instance of exponential backoff with default values for retrying GetAspectType calls
|
// Create an instance of exponential backoff with default values for retrying GetAspectType calls
|
||||||
// InitialInterval, RandomizationFactor, Multiplier, MaxInterval = 500 ms, 0.5, 1.5, 60 s
|
// InitialInterval, RandomizationFactor, Multiplier, MaxInterval = 500 ms, 0.5, 1.5, 60 s
|
||||||
@@ -214,9 +225,17 @@ func (s *Source) SearchEntries(ctx context.Context, query string, pageSize int,
|
|||||||
var results []*dataplexpb.SearchEntriesResult
|
var results []*dataplexpb.SearchEntriesResult
|
||||||
for {
|
for {
|
||||||
entry, err := it.Next()
|
entry, err := it.Next()
|
||||||
if err != nil {
|
if err == iterator.Done {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
if st, ok := grpcstatus.FromError(err); ok {
|
||||||
|
errorCode := st.Code()
|
||||||
|
errorMessage := st.Message()
|
||||||
|
return nil, fmt.Errorf("failed to search entries with error code: %q message: %s", errorCode.String(), errorMessage)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("failed to search entries: %w", err)
|
||||||
|
}
|
||||||
results = append(results, entry)
|
results = append(results, entry)
|
||||||
}
|
}
|
||||||
return results, nil
|
return results, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user