Commit d4dc29c
authored
Extract duplicate error handling patterns into reusable helpers (#811)
Analysis identified 18 instances of duplicated error handling logic
across `internal/server/unified.go` and `internal/mcp/connection.go`.
This consolidates them into tested helper functions.
## Changes
### SDK CallToolResult Error Returns (16 instances)
- Extracted `newErrorCallToolResult(err error) (*sdk.CallToolResult,
interface{}, error)` helper
- Replaces repeated pattern: `return &sdk.CallToolResult{IsError: true},
nil, err`
- Affected: tool handlers, session initialization, backend communication
```go
// Before (repeated 16 times)
if err != nil {
return &sdk.CallToolResult{IsError: true}, nil, err
}
// After
if err != nil {
return newErrorCallToolResult(err)
}
```
### HTTP Connection Error Detection (2 instances)
- Extracted `isHTTPConnectionError(err error) bool` helper
- Consolidates network error classification (connection refused, no such
host, network unreachable)
- Affected: HTTP initialize and request paths
```go
// Before (repeated 2 times)
if strings.Contains(err.Error(), "connection refused") ||
strings.Contains(err.Error(), "no such host") ||
strings.Contains(err.Error(), "network is unreachable") {
// handle connection error
}
// After
if isHTTPConnectionError(err) {
// handle connection error
}
```
### Test Coverage
- Added 8 test cases covering both helpers
- Tests validate error propagation and proper nil handling
## Notes
- Third pattern (command error detection) had only 1 occurrence - not
duplicated, no action taken
- Added TODO for future improvement: replace string matching with
`*net.OpError` type assertions
> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `example.com`
> - Triggering command: `/tmp/go-build3296312196/b271/launcher.test
/tmp/go-build3296312196/b271/launcher.test
-test.testlogfile=/tmp/go-build3296312196/b271/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true
ache/go/1.25.6/x/tmp/tmp.7JmQLDmIdb/golangci-lint-2.8.0-linux-amd64.tar.gz
nto helper functREDACTED x_amd64/vet -pthread -Wl,--no-gc-sect-o
-fmessage-length/tmp/go-build1663340372/b266/_pkg_.a x_amd64/vet -I
ache/go/1.25.6/x-p -fPIC x_amd64/vet -pthread -Wl,--no-gc-sect-o
-fmessage-length/tmp/go-build3296312196/b259/_pkg_.a x_amd64/vet` (dns
block)
> - Triggering command: `/tmp/go-build3756687988/b271/launcher.test
/tmp/go-build3756687988/b271/launcher.test
-test.testlogfile=/tmp/go-build3756687988/b271/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true` (dns block)
> - `invalid-host-that-does-not-exist-12345.com`
> - Triggering command: `/tmp/go-build3296312196/b259/config.test
/tmp/go-build3296312196/b259/config.test
-test.testlogfile=/tmp/go-build3296312196/b259/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true -c=4 -nolocalimports
-importcfg /tmp/go-build1663340372/b283/importcfg -pack
/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/internal/testutil/mcptest/example_test.go
/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/internal/testutil/mcptest/gateway_integration_test.go
64/s�� ache/go/1.25.6/x64/src/net nto helper functions
- Pattern 2 (High Priority): Extract SDK CallToolResult error returns
- test x_amd64/vet --gdwarf-5 --64 -o x_amd64/vet` (dns block)
> - `nonexistent.local`
> - Triggering command: `/tmp/go-build3296312196/b271/launcher.test
/tmp/go-build3296312196/b271/launcher.test
-test.testlogfile=/tmp/go-build3296312196/b271/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true
ache/go/1.25.6/x/tmp/tmp.7JmQLDmIdb/golangci-lint-2.8.0-linux-amd64.tar.gz
nto helper functREDACTED x_amd64/vet -pthread -Wl,--no-gc-sect-o
-fmessage-length/tmp/go-build1663340372/b266/_pkg_.a x_amd64/vet -I
ache/go/1.25.6/x-p -fPIC x_amd64/vet -pthread -Wl,--no-gc-sect-o
-fmessage-length/tmp/go-build3296312196/b259/_pkg_.a x_amd64/vet` (dns
block)
> - Triggering command: `/tmp/go-build3756687988/b271/launcher.test
/tmp/go-build3756687988/b271/launcher.test
-test.testlogfile=/tmp/go-build3756687988/b271/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true` (dns block)
> - `slow.example.com`
> - Triggering command: `/tmp/go-build3296312196/b271/launcher.test
/tmp/go-build3296312196/b271/launcher.test
-test.testlogfile=/tmp/go-build3296312196/b271/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true
ache/go/1.25.6/x/tmp/tmp.7JmQLDmIdb/golangci-lint-2.8.0-linux-amd64.tar.gz
nto helper functREDACTED x_amd64/vet -pthread -Wl,--no-gc-sect-o
-fmessage-length/tmp/go-build1663340372/b266/_pkg_.a x_amd64/vet -I
ache/go/1.25.6/x-p -fPIC x_amd64/vet -pthread -Wl,--no-gc-sect-o
-fmessage-length/tmp/go-build3296312196/b259/_pkg_.a x_amd64/vet` (dns
block)
> - Triggering command: `/tmp/go-build3756687988/b271/launcher.test
/tmp/go-build3756687988/b271/launcher.test
-test.testlogfile=/tmp/go-build3756687988/b271/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true` (dns block)
> - `this-host-does-not-exist-12345.com`
> - Triggering command: `/tmp/go-build668030957/b001/mcp.test
/tmp/go-build668030957/b001/mcp.test
-test.testlogfile=/tmp/go-build668030957/b001/testlog.txt
-test.paniconexit0 -test.timeout=10m0s conf�� 64/src/runtime/c-c=4
credential.usern-nolocalimports .12/x64/bin/as` (dns block)
> - Triggering command: `/tmp/go-build3296312196/b280/mcp.test
/tmp/go-build3296312196/b280/mcp.test
-test.testlogfile=/tmp/go-build3296312196/b280/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true -c=4 -nolocalimports
-importcfg /tmp/go-build3296312196/b282/importcfg -pack
/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/internal/middleware/jqschema.go
/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/internal/middleware/jqschema_bench_test.go`
(dns block)
> - Triggering command: `/tmp/go-build3756687988/b280/mcp.test
/tmp/go-build3756687988/b280/mcp.test
-test.testlogfile=/tmp/go-build3756687988/b280/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true` (dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/github/gh-aw-mcpg/settings/copilot/coding_agent)
(admins only)
>
> </details>
<!-- START COPILOT ORIGINAL PROMPT -->
<details>
<summary>Original prompt</summary>
>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>[duplicate-code] Duplicate Code Analysis Report - 3
Patterns Detected</issue_title>
> <issue_description># 🔍 Duplicate Code Analysis Report
>
> *Analysis of commit 06ff18a*
>
> ## Summary
>
> This analysis identified **3 significant duplication patterns** across
the Go codebase, primarily in error handling and HTTP connection logic.
While the project has already refactored some areas (e.g., logger
initialization with generics), several high-impact patterns remain.
>
> ## Detected Patterns
>
> This analysis found 3 significant duplication patterns:
>
> 1. **HTTP Connection Error Checking** - Severity: Medium - See
sub-issue #740
> 2. **SDK CallToolResult Error Returns** - Severity: High - See
sub-issue #741
> 3. **Command Error Detection Logic** - Severity: Low - See sub-issue
#742
>
> ## Overall Impact
>
> - **Total Duplicated Lines**: ~45 lines of duplicated logic
> - **Affected Files**: 2 files (`internal/mcp/connection.go`,
`internal/server/unified.go`)
> - **Maintainability Risk**: Medium - Error handling duplication
increases bug risk
> - **Refactoring Priority**: **High** for pattern #2,
Medium for pattern #1, Low for pattern
#3
>
> ## Next Steps
>
> 1. Review individual pattern sub-issues for detailed analysis
> 2. Prioritize refactoring based on severity and impact
> 3. Create implementation plan for highest priority patterns
>
> ## Analysis Metadata
>
> - **Analyzed Files**: 60+ Go files in `internal/` directory
> - **Detection Method**: Serena semantic code analysis + pattern
matching
> - **Commit**: 06ff18a
> - **Analysis Date**: 2026-02-06</issue_description>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> </comments>
>
</details>
> **Custom agent used: agentic-workflows**
> GitHub Agentic Workflows (gh-aw) - Create, debug, and upgrade
AI-powered workflows with intelligent prompt routing
<!-- START COPILOT CODING AGENT SUFFIX -->
- Fixes #739
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.4 files changed
Lines changed: 125 additions & 22 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
26 | 40 | | |
27 | 41 | | |
28 | 42 | | |
| |||
584 | 598 | | |
585 | 599 | | |
586 | 600 | | |
587 | | - | |
588 | | - | |
589 | | - | |
| 601 | + | |
590 | 602 | | |
591 | 603 | | |
592 | 604 | | |
| |||
698 | 710 | | |
699 | 711 | | |
700 | 712 | | |
701 | | - | |
702 | | - | |
703 | | - | |
| 713 | + | |
704 | 714 | | |
705 | 715 | | |
706 | 716 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
703 | 703 | | |
704 | 704 | | |
705 | 705 | | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
151 | 152 | | |
152 | 153 | | |
153 | 154 | | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
320 | 320 | | |
321 | 321 | | |
322 | 322 | | |
323 | | - | |
| 323 | + | |
324 | 324 | | |
325 | 325 | | |
326 | 326 | | |
| |||
331 | 331 | | |
332 | 332 | | |
333 | 333 | | |
334 | | - | |
| 334 | + | |
335 | 335 | | |
336 | 336 | | |
337 | 337 | | |
| |||
395 | 395 | | |
396 | 396 | | |
397 | 397 | | |
398 | | - | |
| 398 | + | |
399 | 399 | | |
400 | 400 | | |
401 | 401 | | |
| |||
408 | 408 | | |
409 | 409 | | |
410 | 410 | | |
411 | | - | |
| 411 | + | |
412 | 412 | | |
413 | 413 | | |
414 | 414 | | |
| |||
436 | 436 | | |
437 | 437 | | |
438 | 438 | | |
439 | | - | |
| 439 | + | |
440 | 440 | | |
441 | 441 | | |
442 | 442 | | |
| |||
486 | 486 | | |
487 | 487 | | |
488 | 488 | | |
489 | | - | |
| 489 | + | |
490 | 490 | | |
491 | 491 | | |
492 | 492 | | |
| |||
496 | 496 | | |
497 | 497 | | |
498 | 498 | | |
499 | | - | |
| 499 | + | |
500 | 500 | | |
501 | 501 | | |
502 | 502 | | |
| |||
657 | 657 | | |
658 | 658 | | |
659 | 659 | | |
660 | | - | |
| 660 | + | |
661 | 661 | | |
662 | 662 | | |
663 | 663 | | |
| |||
688 | 688 | | |
689 | 689 | | |
690 | 690 | | |
691 | | - | |
| 691 | + | |
692 | 692 | | |
693 | 693 | | |
694 | 694 | | |
695 | 695 | | |
696 | 696 | | |
697 | 697 | | |
698 | 698 | | |
699 | | - | |
| 699 | + | |
700 | 700 | | |
701 | 701 | | |
702 | 702 | | |
703 | 703 | | |
704 | | - | |
| 704 | + | |
705 | 705 | | |
706 | 706 | | |
707 | 707 | | |
708 | 708 | | |
709 | 709 | | |
710 | | - | |
| 710 | + | |
711 | 711 | | |
712 | 712 | | |
713 | 713 | | |
714 | 714 | | |
715 | 715 | | |
716 | 716 | | |
717 | | - | |
| 717 | + | |
718 | 718 | | |
719 | 719 | | |
720 | 720 | | |
| |||
735 | 735 | | |
736 | 736 | | |
737 | 737 | | |
738 | | - | |
| 738 | + | |
739 | 739 | | |
740 | 740 | | |
741 | 741 | | |
742 | 742 | | |
743 | 743 | | |
744 | | - | |
| 744 | + | |
745 | 745 | | |
746 | 746 | | |
747 | 747 | | |
| |||
767 | 767 | | |
768 | 768 | | |
769 | 769 | | |
770 | | - | |
| 770 | + | |
771 | 771 | | |
772 | 772 | | |
773 | 773 | | |
| |||
779 | 779 | | |
780 | 780 | | |
781 | 781 | | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
782 | 789 | | |
783 | 790 | | |
784 | 791 | | |
| |||
0 commit comments