Repository navigation
Expand file tree
/
Copy patherrors.go
More file actions
81 lines (76 loc) · 2.45 KB
/
Copy patherrors.go
File metadata and controls
81 lines (76 loc) · 2.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package protocolbridge
// Provider errors cross protocol boundaries in this package as the decoded
// JSON value each decoder happened to receive: a bare string for some gateways,
// an object for the three protocols we speak, and sometimes an object wrapped
// one level down. The readers below tolerate every shape so that an upstream
// failure survives the conversion instead of turning into "<nil>" or a Go map's
// fmt.Sprint rendering.
// errorMessage returns a human-readable message for a decoded provider error.
//
// A bare string is the message itself. An object may nest the real detail under
// "error" (Anthropic's {"type":"error","error":{...}}), so that level is tried
// first before the flat message keys.
func errorMessage(value any) string {
switch typed := value.(type) {
case nil:
return ""
case string:
return typed
case map[string]any:
if nested, ok := typed["error"]; ok {
if message := errorMessage(nested); message != "" {
return message
}
}
for _, key := range []string{"message", "error_description", "detail"} {
if text, ok := typed[key].(string); ok && text != "" {
return text
}
}
}
return ""
}
// errorCode returns the provider's error code, falling back to its error type.
// Unlike errorMessage it never treats a bare string as a code.
func errorCode(value any) string {
switch typed := value.(type) {
case map[string]any:
if nested, ok := typed["error"]; ok {
if code := errorCode(nested); code != "" {
return code
}
}
for _, key := range []string{"code", "type"} {
if text, ok := typed[key].(string); ok && text != "" {
return text
}
}
}
return ""
}
// errorParam returns the offending request field when the provider names one.
func errorParam(value any) string {
switch typed := value.(type) {
case map[string]any:
if nested, ok := typed["error"]; ok {
if param := errorParam(nested); param != "" {
return param
}
}
if text, ok := typed["param"].(string); ok {
return text
}
}
return ""
}
// anthropicErrorType maps a provider error code onto Anthropic's closed set of
// error types. Claude Code validates error.type, so an OpenAI code such as
// "server_error" must not be passed through verbatim.
func anthropicErrorType(value any) string {
switch errorCode(value) {
case "invalid_request_error", "authentication_error", "permission_error",
"not_found_error", "rate_limit_error", "api_error", "overloaded_error":
return errorCode(value)
}
return "api_error"
}