This commit is contained in:
2026-08-17 21:56:09 +02:00
parent 6fcdc74843
commit a7e53ca0a3
6 changed files with 162 additions and 56 deletions
+16 -6
View File
@@ -68,8 +68,8 @@ func truncateRunes(s string, max int) string {
}
const (
publicErrProcessingFailed = "processing_failed"
publicErrProviderUnavailable = "provider_unavailable"
publicErrProcessingFailed = "processing_failed"
publicErrProviderUnavailable = "provider_unavailable"
)
// TruncateError returns a safe, short error string for DB storage / API clients.
@@ -139,6 +139,9 @@ func PublicV1Error(msg string) string {
if code := mapPublicErrorCode(cleaned); code != "" {
return code
}
if code := mapPublicV1FallbackCode(cleaned); code != "" {
return code
}
if looksLikeInternalProviderError(cleaned) {
return publicErrProcessingFailed
}
@@ -172,10 +175,6 @@ func mapPublicErrorCode(msg string) string {
return publicErrProviderUnavailable
case strings.Contains(lower, "ai_enhance: skipped"):
return publicErrProcessingFailed
case strings.Contains(lower, "unavailable"),
strings.Contains(lower, "http 503"),
strings.Contains(lower, "overloaded"):
return publicErrProviderUnavailable
case strings.Contains(lower, "openai"),
strings.Contains(lower, "gpt-"),
strings.Contains(lower, " for model"):
@@ -184,6 +183,17 @@ func mapPublicErrorCode(msg string) string {
return ""
}
func mapPublicV1FallbackCode(msg string) string {
lower := strings.ToLower(strings.TrimSpace(msg))
switch {
case strings.Contains(lower, "unavailable"),
strings.Contains(lower, "http 503"),
strings.Contains(lower, "overloaded"):
return publicErrProviderUnavailable
}
return ""
}
func looksLikeInternalProviderError(msg string) bool {
lower := strings.ToLower(msg)
for _, n := range []string{
+6 -12
View File
@@ -62,14 +62,6 @@ func TestTruncateError_mapsInternalProviderLeaks(t *testing.T) {
in: "ai_enhance: skipped (platform OpenAI unset; configure admin settings or company BYOK)",
want: "provider_unavailable",
},
{
in: "openai retries exhausted: green-chat unavailable",
want: "provider_unavailable",
},
{
in: "upstream 503: model overloaded",
want: "provider_unavailable",
},
}
for _, tc := range cases {
got := TruncateError(errString(tc.in))
@@ -91,6 +83,8 @@ func TestPublicV1Error_stripsProviderInternals(t *testing.T) {
}{
{in: `openai length-capped at max_tokens=8000 for model "gpt-4o"`, want: "processing_failed"},
{in: "ai_enhance: skipped (platform OpenAI unset; configure admin settings or company BYOK)", want: "provider_unavailable"},
{in: "openai retries exhausted: green-chat unavailable", want: "provider_unavailable"},
{in: "upstream 503: model overloaded", want: "provider_unavailable"},
{in: "processing_failed", want: "processing_failed"},
{in: "Product data not available", want: "Product data not available"},
{in: "processing.job.error.all_failed|count=3", want: "processing.job.error.all_failed|count=3"},
@@ -122,13 +116,13 @@ func TestTruncateError_classifiesProviderFailures(t *testing.T) {
want: "AI provider timed out",
},
{
in: "unauthorized", want: "AI provider rejected the API key"},
in: "unauthorized", want: "AI provider rejected the API key"},
{
in: "openai http 401", want: "AI provider rejected the API key"},
in: "openai http 401", want: "AI provider rejected the API key"},
{in: "rate limited or server error", want: "AI provider temporarily unavailable"},
{in: "too many requests", want: "AI provider rate limited"},
{in: "upstream 503: model overloaded", want: "provider_unavailable"},
{in: "openai retries exhausted: green-chat unavailable", want: "provider_unavailable"},
{in: "upstream 503: model overloaded", want: "upstream 503: model overloaded"},
{in: "openai retries exhausted: green-chat unavailable", want: "green-chat unavailable"},
}
for _, tc := range cases {
got := TruncateError(errString(tc.in))