llm-errors 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +28 -5
  3. package/dist/index.cjs +133 -31
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +8 -5
  6. package/dist/index.d.ts +8 -5
  7. package/dist/index.js +133 -31
  8. package/dist/index.js.map +1 -1
  9. package/fixtures/README.md +28 -0
  10. package/fixtures/cases/anthropic/fetch-context-length.json +17 -0
  11. package/fixtures/cases/anthropic/fetch-rate-limit.json +18 -0
  12. package/fixtures/cases/anthropic/rate-limit-credit-balance.json +17 -0
  13. package/fixtures/cases/anthropic/sdk-billing-error.json +14 -0
  14. package/fixtures/cases/anthropic/sdk-overloaded-529.json +17 -0
  15. package/fixtures/cases/gemini/fetch-unavailable.json +19 -0
  16. package/fixtures/cases/gemini/plain-unavailable-body.json +9 -0
  17. package/fixtures/cases/gemini/rpc-permission-denied.json +11 -0
  18. package/fixtures/cases/gemini/rpc-quota-exhausted-billing.json +11 -0
  19. package/fixtures/cases/gemini/rpc-quota-exhausted-rate-bucket.json +11 -0
  20. package/fixtures/cases/gemini/rpc-resource-exhausted.json +17 -0
  21. package/fixtures/cases/generic/http-400-retry-after.json +15 -0
  22. package/fixtures/cases/generic/http-503-retry-after.json +15 -0
  23. package/fixtures/cases/network/abort-error.json +8 -0
  24. package/fixtures/cases/network/node-timeout.json +9 -0
  25. package/fixtures/cases/openai/fetch-context-length.json +18 -0
  26. package/fixtures/cases/openai/plain-rate-limit-body.json +10 -0
  27. package/fixtures/cases/openai/sdk-billing-hard-limit.json +12 -0
  28. package/fixtures/cases/openai/sdk-insufficient-quota.json +13 -0
  29. package/fixtures/cases/openai/sdk-rate-limit.json +18 -0
  30. package/fixtures/expected/anthropic/fetch-context-length.json +8 -0
  31. package/fixtures/expected/anthropic/fetch-rate-limit.json +9 -0
  32. package/fixtures/expected/anthropic/rate-limit-credit-balance.json +8 -0
  33. package/fixtures/expected/anthropic/sdk-billing-error.json +8 -0
  34. package/fixtures/expected/anthropic/sdk-overloaded-529.json +8 -0
  35. package/fixtures/expected/gemini/fetch-unavailable.json +9 -0
  36. package/fixtures/expected/gemini/plain-unavailable-body.json +8 -0
  37. package/fixtures/expected/gemini/rpc-permission-denied.json +8 -0
  38. package/fixtures/expected/gemini/rpc-quota-exhausted-billing.json +8 -0
  39. package/fixtures/expected/gemini/rpc-quota-exhausted-rate-bucket.json +8 -0
  40. package/fixtures/expected/gemini/rpc-resource-exhausted.json +9 -0
  41. package/fixtures/expected/generic/http-400-retry-after.json +7 -0
  42. package/fixtures/expected/generic/http-503-retry-after.json +8 -0
  43. package/fixtures/expected/network/abort-error.json +7 -0
  44. package/fixtures/expected/network/node-timeout.json +7 -0
  45. package/fixtures/expected/openai/fetch-context-length.json +8 -0
  46. package/fixtures/expected/openai/plain-rate-limit-body.json +7 -0
  47. package/fixtures/expected/openai/sdk-billing-hard-limit.json +7 -0
  48. package/fixtures/expected/openai/sdk-insufficient-quota.json +8 -0
  49. package/fixtures/expected/openai/sdk-rate-limit.json +9 -0
  50. package/package.json +3 -2
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "Anthropic SDK billing error",
3
+ "shape": "anthropic-sdk-error-envelope",
4
+ "error": {
5
+ "status": 429,
6
+ "error": {
7
+ "type": "error",
8
+ "error": {
9
+ "type": "billing_error",
10
+ "message": "Your credit balance is too low."
11
+ }
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "Anthropic SDK overloaded response",
3
+ "shape": "anthropic-sdk-apierror",
4
+ "error": {
5
+ "status": 529,
6
+ "headers": {
7
+ "anthropic-version": "2023-06-01"
8
+ },
9
+ "error": {
10
+ "type": "error",
11
+ "error": {
12
+ "type": "overloaded_error",
13
+ "message": "Overloaded"
14
+ }
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "Gemini parsed fetch response unavailable",
3
+ "shape": "google-rpc-fetch-parsed-body",
4
+ "error": {
5
+ "response": {
6
+ "status": 503,
7
+ "headers": {
8
+ "retry-after": "4"
9
+ },
10
+ "data": {
11
+ "error": {
12
+ "code": 503,
13
+ "message": "The model is overloaded. Please try again later.",
14
+ "status": "UNAVAILABLE"
15
+ }
16
+ }
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "Gemini direct plain unavailable body",
3
+ "shape": "plain-provider-error-body",
4
+ "error": {
5
+ "code": 503,
6
+ "message": "The model is overloaded. Please try again later.",
7
+ "status": "UNAVAILABLE"
8
+ }
9
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "Gemini Google RPC permission denied",
3
+ "shape": "google-rpc-error-envelope",
4
+ "error": {
5
+ "error": {
6
+ "code": 403,
7
+ "message": "The caller does not have permission.",
8
+ "status": "PERMISSION_DENIED"
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "Gemini Google RPC quota exhausted billing",
3
+ "shape": "google-rpc-error-envelope",
4
+ "error": {
5
+ "error": {
6
+ "code": 429,
7
+ "message": "You exceeded your current quota, please check your plan and billing details.",
8
+ "status": "RESOURCE_EXHAUSTED"
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "Gemini RESOURCE_EXHAUSTED rate bucket without billing signal",
3
+ "shape": "google-rpc-error-body",
4
+ "error": {
5
+ "error": {
6
+ "code": 429,
7
+ "message": "Quota exceeded for requests per minute.",
8
+ "status": "RESOURCE_EXHAUSTED"
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "Gemini Google RPC resource exhausted",
3
+ "shape": "google-rpc-error-envelope",
4
+ "error": {
5
+ "error": {
6
+ "code": 429,
7
+ "message": "Resource has been exhausted.",
8
+ "status": "RESOURCE_EXHAUSTED",
9
+ "details": [
10
+ {
11
+ "@type": "type.googleapis.com/google.rpc.RetryInfo",
12
+ "retryDelay": "17s"
13
+ }
14
+ ]
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "Generic HTTP 400 with ignored Retry-After",
3
+ "shape": "fetch-like-http-error",
4
+ "error": {
5
+ "statusCode": 400,
6
+ "headers": {
7
+ "Retry-After": "60"
8
+ },
9
+ "body": {
10
+ "error": {
11
+ "message": "Bad request"
12
+ }
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "Generic HTTP 503 with Retry-After",
3
+ "shape": "fetch-like-http-error",
4
+ "error": {
5
+ "statusCode": 503,
6
+ "headers": {
7
+ "Retry-After": "6"
8
+ },
9
+ "body": {
10
+ "error": {
11
+ "message": "Service temporarily unavailable"
12
+ }
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "Browser fetch abort",
3
+ "shape": "dom-abort-error",
4
+ "error": {
5
+ "name": "AbortError",
6
+ "message": "The operation was aborted."
7
+ }
8
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "Node transport timeout",
3
+ "shape": "node-error-code",
4
+ "error": {
5
+ "name": "Error",
6
+ "message": "connect ETIMEDOUT",
7
+ "code": "ETIMEDOUT"
8
+ }
9
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "OpenAI parsed fetch response context length",
3
+ "shape": "openai-fetch-parsed-body",
4
+ "error": {
5
+ "status": 400,
6
+ "headers": {
7
+ "openai-processing-ms": "42"
8
+ },
9
+ "body": {
10
+ "error": {
11
+ "message": "This model's maximum context length is 128000 tokens.",
12
+ "type": "invalid_request_error",
13
+ "code": "context_length_exceeded",
14
+ "param": "messages"
15
+ }
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "OpenAI direct plain rate limit body",
3
+ "shape": "plain-provider-error-body",
4
+ "error": {
5
+ "message": "Rate limit reached for requests",
6
+ "type": "rate_limit_error",
7
+ "code": "rate_limit_exceeded",
8
+ "param": null
9
+ }
10
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "OpenAI SDK billing hard limit",
3
+ "shape": "openai-sdk-api-error",
4
+ "error": {
5
+ "error": {
6
+ "message": "Billing hard limit has been reached",
7
+ "type": "invalid_request_error",
8
+ "code": "billing_hard_limit_reached",
9
+ "param": null
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "OpenAI SDK APIError insufficient quota",
3
+ "shape": "openai-sdk-apierror",
4
+ "error": {
5
+ "status": 429,
6
+ "error": {
7
+ "message": "You exceeded your current quota.",
8
+ "type": "insufficient_quota",
9
+ "code": "insufficient_quota",
10
+ "param": null
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "OpenAI SDK APIError rate limit",
3
+ "shape": "openai-sdk-apierror",
4
+ "error": {
5
+ "status": 429,
6
+ "headers": {
7
+ "openai-version": "2020-10-01",
8
+ "retry-after-ms": "1250",
9
+ "retry-after": "2"
10
+ },
11
+ "error": {
12
+ "message": "Rate limit reached for requests",
13
+ "type": "rate_limit_error",
14
+ "code": "rate_limit_exceeded",
15
+ "param": null
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "anthropic",
3
+ "category": "context_length_exceeded",
4
+ "message": "prompt is too long: 250000 tokens > 200000 maximum",
5
+ "status": 400,
6
+ "code": "invalid_request_error",
7
+ "retryable": false
8
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "provider": "anthropic",
3
+ "category": "rate_limit",
4
+ "message": "rate limit exceeded",
5
+ "status": 429,
6
+ "code": "rate_limit_error",
7
+ "retryable": true,
8
+ "retryAfterMs": 30000
9
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "anthropic",
3
+ "category": "insufficient_quota",
4
+ "message": "Your credit balance is too low.",
5
+ "status": 429,
6
+ "code": "rate_limit_error",
7
+ "retryable": false
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "anthropic",
3
+ "category": "insufficient_quota",
4
+ "message": "Your credit balance is too low.",
5
+ "status": 429,
6
+ "code": "billing_error",
7
+ "retryable": false
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "anthropic",
3
+ "category": "overloaded",
4
+ "message": "Overloaded",
5
+ "status": 529,
6
+ "code": "overloaded_error",
7
+ "retryable": true
8
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "provider": "gemini",
3
+ "category": "overloaded",
4
+ "message": "The model is overloaded. Please try again later.",
5
+ "status": 503,
6
+ "code": "UNAVAILABLE",
7
+ "retryable": true,
8
+ "retryAfterMs": 4000
9
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "gemini",
3
+ "category": "overloaded",
4
+ "message": "The model is overloaded. Please try again later.",
5
+ "status": 503,
6
+ "code": "UNAVAILABLE",
7
+ "retryable": true
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "gemini",
3
+ "category": "permission",
4
+ "message": "The caller does not have permission.",
5
+ "status": 403,
6
+ "code": "PERMISSION_DENIED",
7
+ "retryable": false
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "gemini",
3
+ "category": "insufficient_quota",
4
+ "message": "You exceeded your current quota, please check your plan and billing details.",
5
+ "status": 429,
6
+ "code": "RESOURCE_EXHAUSTED",
7
+ "retryable": false
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "gemini",
3
+ "category": "rate_limit",
4
+ "message": "Quota exceeded for requests per minute.",
5
+ "status": 429,
6
+ "code": "RESOURCE_EXHAUSTED",
7
+ "retryable": true
8
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "provider": "gemini",
3
+ "category": "rate_limit",
4
+ "message": "Resource has been exhausted.",
5
+ "status": 429,
6
+ "code": "RESOURCE_EXHAUSTED",
7
+ "retryable": true,
8
+ "retryAfterMs": 17000
9
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "provider": "unknown",
3
+ "category": "invalid_request",
4
+ "message": "Bad request",
5
+ "status": 400,
6
+ "retryable": false
7
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "unknown",
3
+ "category": "overloaded",
4
+ "message": "Service temporarily unavailable",
5
+ "status": 503,
6
+ "retryable": true,
7
+ "retryAfterMs": 6000
8
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "provider": "unknown",
3
+ "category": "timeout",
4
+ "message": "The operation was aborted.",
5
+ "code": "AbortError",
6
+ "retryable": true
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "provider": "unknown",
3
+ "category": "timeout",
4
+ "message": "connect ETIMEDOUT",
5
+ "code": "ETIMEDOUT",
6
+ "retryable": true
7
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "openai",
3
+ "category": "context_length_exceeded",
4
+ "message": "This model's maximum context length is 128000 tokens.",
5
+ "status": 400,
6
+ "code": "context_length_exceeded",
7
+ "retryable": false
8
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "provider": "openai",
3
+ "category": "rate_limit",
4
+ "message": "Rate limit reached for requests",
5
+ "code": "rate_limit_exceeded",
6
+ "retryable": true
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "provider": "openai",
3
+ "category": "insufficient_quota",
4
+ "message": "Billing hard limit has been reached",
5
+ "code": "billing_hard_limit_reached",
6
+ "retryable": false
7
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "provider": "openai",
3
+ "category": "insufficient_quota",
4
+ "message": "You exceeded your current quota.",
5
+ "status": 429,
6
+ "code": "insufficient_quota",
7
+ "retryable": false
8
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "provider": "openai",
3
+ "category": "rate_limit",
4
+ "message": "Rate limit reached for requests",
5
+ "status": 429,
6
+ "code": "rate_limit_exceeded",
7
+ "retryable": true,
8
+ "retryAfterMs": 1250
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-errors",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Normalize OpenAI, Anthropic and Gemini API errors into one shape: category, retryable flag and Retry-After delay. Zero dependencies.",
5
5
  "keywords": [
6
6
  "openai",
@@ -46,6 +46,7 @@
46
46
  },
47
47
  "files": [
48
48
  "dist",
49
+ "fixtures",
49
50
  "README.md",
50
51
  "LICENSE",
51
52
  "CHANGELOG.md"
@@ -71,7 +72,7 @@
71
72
  "eslint": "^10.4.1",
72
73
  "prettier": "^3.4.2",
73
74
  "tsup": "^8.3.5",
74
- "typescript": "^5.7.2",
75
+ "typescript": "^6.0.3",
75
76
  "typescript-eslint": "^8.60.0",
76
77
  "vitest": "^4.1.8"
77
78
  }