Skip to content

Commit ce40a67

Browse files
authored
Add unsupportedUserLocation case to GenerateContentError (#85)
1 parent db2da90 commit ce40a67

File tree

5 files changed

+71
-0
lines changed

5 files changed

+71
-0
lines changed

Sources/GoogleAI/Errors.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ struct RPCError: Error {
3434
func isInvalidAPIKeyError() -> Bool {
3535
return errorInfo?.reason == "API_KEY_INVALID"
3636
}
37+
38+
func isUnsupportedUserLocationError() -> Bool {
39+
return message == RPCErrorMessage.unsupportedUserLocation.rawValue
40+
}
3741
}
3842

3943
extension RPCError: Decodable {
@@ -175,6 +179,10 @@ enum RPCStatus: String, Decodable {
175179
case dataLoss = "DATA_LOSS"
176180
}
177181

182+
enum RPCErrorMessage: String {
183+
case unsupportedUserLocation = "User location is not supported for the API use."
184+
}
185+
178186
enum InvalidCandidateError: Error {
179187
case emptyContent(underlyingError: Error)
180188
case malformedContent(underlyingError: Error)

Sources/GoogleAI/GenerateContentError.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,14 @@ public enum GenerateContentError: Error {
2727

2828
/// The provided API key is invalid.
2929
case invalidAPIKey
30+
31+
/// The user's location (region) is not supported by the API.
32+
///
33+
/// See the Google documentation for a
34+
/// [list of regions](https://ai.google.dev/available_regions#available_regions)
35+
/// (countries and territories) where the API is available.
36+
///
37+
/// - Important: The API is only available in
38+
/// [specific regions](https://ai.google.dev/available_regions#available_regions).
39+
case unsupportedUserLocation
3040
}

Sources/GoogleAI/GenerativeModel.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ public final class GenerativeModel {
246246
return error
247247
} else if let error = error as? RPCError, error.isInvalidAPIKeyError() {
248248
return GenerateContentError.invalidAPIKey
249+
} else if let error = error as? RPCError, error.isUnsupportedUserLocationError() {
250+
return GenerateContentError.unsupportedUserLocation
249251
}
250252
return GenerateContentError.internalError(underlying: error)
251253
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"error": {
3+
"code": 400,
4+
"message": "User location is not supported for the API use.",
5+
"status": "FAILED_PRECONDITION",
6+
"details": [
7+
{
8+
"@type": "type.googleapis.com/google.rpc.DebugInfo",
9+
"detail": "[ORIGINAL ERROR] generic::failed_precondition: User location is not supported for the API use. [google.rpc.error_details_ext] { message: \"User location is not supported for the API use.\" }"
10+
}
11+
]
12+
}
13+
}

Tests/GoogleAITests/GenerativeModelTests.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,24 @@ final class GenerativeModelTests: XCTestCase {
342342
}
343343
}
344344

345+
func testGenerateContent_failure_unsupportedUserLocation() async throws {
346+
MockURLProtocol
347+
.requestHandler = try httpRequestHandler(
348+
forResource: "unary-failure-unsupported-user-location",
349+
withExtension: "json",
350+
statusCode: 400
351+
)
352+
353+
do {
354+
_ = try await model.generateContent(testPrompt)
355+
XCTFail("Should throw GenerateContentError.unsupportedUserLocation; no error thrown.")
356+
} catch GenerateContentError.unsupportedUserLocation {
357+
return
358+
}
359+
360+
XCTFail("Expected an unsupported user location error.")
361+
}
362+
345363
func testGenerateContent_failure_nonHTTPResponse() async throws {
346364
MockURLProtocol.requestHandler = try nonHTTPRequestHandler()
347365

@@ -708,6 +726,26 @@ final class GenerativeModelTests: XCTestCase {
708726
XCTFail("Expected an internal decoding error.")
709727
}
710728

729+
func testGenerateContentStream_failure_unsupportedUserLocation() async throws {
730+
MockURLProtocol
731+
.requestHandler = try httpRequestHandler(
732+
forResource: "unary-failure-unsupported-user-location",
733+
withExtension: "json",
734+
statusCode: 400
735+
)
736+
737+
let stream = model.generateContentStream(testPrompt)
738+
do {
739+
for try await content in stream {
740+
XCTFail("Unexpected content in stream: \(content)")
741+
}
742+
} catch GenerateContentError.unsupportedUserLocation {
743+
return
744+
}
745+
746+
XCTFail("Expected an unsupported user location error.")
747+
}
748+
711749
// MARK: - Count Tokens
712750

713751
func testCountTokens_succeeds() async throws {

0 commit comments

Comments
 (0)