Swift: Call can throw, but it is not marked with 'try' and the error is not handled


In Swift, when you call a function that throws an error, you must either mark the function call with the try keyword or handle the error using a do-catch block.

If you see the error message "Call can throw, but it is not marked with 'try' and the error is not handled", it means that you have called a function that can throw an error, but you have not handled the error properly.

How to Fix These Errors?

Mark the function call with the try keyword. For example 

do {
   let result = try someFunctionThatCanThrow()
   // Handle the result
} catch {
   // Handle the error
}

Handle the error using a do-catch block. For example 

do {
   let result = someFunctionThatCanThrow()
   // Handle the result
} catch {
   // Handle the error
}

In either case, you need to handle the error to ensure that your code is robust and can handle unexpected situations.

Example 1

Consider a function divide that takes two numbers as input and returns the result of dividing the first number by the second number. However, if the second number is zero, the function throws an error.

import Foundation
func divide(_ dividend: Int, by divisor: Int) throws -> Int {
   guard divisor != 0 else {
      throw NSError(domain: "com.example", code: 0, userInfo: [
         NSLocalizedDescriptionKey: "Cannot divide by zero"
      ])
   }
   return dividend / divisor
}

In this example, we have marked the function with the throws keyword to indicate that it can throw an error. The function throws an error if the divisor input is zero.

Now, let's say we call the divide function like this −

let result = divide(10, by: 0)

This code will result in the following error message −

error: call can throw but is not marked with 'try'
let result = divide(10, by: 0)

The error message is telling us that the divide function can throw an error, but we have not marked the function call with try nor handled the error.

We can fix this error message in this way −

import Foundation
func divide(_ dividend: Int, by divisor: Int) throws -> Int {
   guard divisor != 0 else {
      throw NSError(domain: "com.example", code: 0, userInfo: [
         NSLocalizedDescriptionKey: "Cannot divide by zero"
      ])
   }
   return dividend / divisor
}
do {
   let result = try divide(10, by: 0)
   print(result)
} catch let err {
   print("Error found: \(err)")
}

Output

Error found: Error Domain=com.example Code=0 "(null)"

This will catch the error thrown by the divide function and execute the catch block.

Example 2

In this example, we want to read the contents of a file into a string. We use the String(contentsOf:encoding:) initializer to read the file. However, this initializer can throw an error if the file is not found or cannot be read.

let filename = "example.txt"
let contents = String(contentsOfFile: filename, encoding: .utf8)
print(contents)

This code will result in the error message "Call can throw, but it is not marked with 'try' and the error is not handled". To fix this error, we can mark the initializer with try or handle the error using a do-catch block.

import Foundation
let filename = "example.txt"
do {
   let contents = try String(contentsOfFile: filename, encoding: .utf8)
   print(contents)
} catch {
   print(error.localizedDescription)
}

Output

The operation could not be completed. No such file or directory

Example 3

In this example, we want to parse JSON data from a web service. We use the JSONSerialization.jsonObject(with:options:) method to parse the JSON data. However, this method can throw an error if the data is not valid JSON.

let data = Data() // JSON data from web service
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)

This code will result in the error message "Call can throw, but it is not marked with 'try' and the error is not handled". To fix this error, we can mark the method with try or handle the error using a do-catch block.

Here is the solution 

import Foundation
let data = Data() // JSON data from web service
do {
   let json = try JSONSerialization.jsonObject(with: data, options: [])
   print(json)
} catch {
   print(error.localizedDescription)
}

Output

Here is the message that will print to the console −

The operation could not be completed. The data is not in the correct format.

Conclusion

In Swift, a function or method can be marked with the throws keyword to indicate that it can throw an error. When calling such a function or method, we need to either mark the call with try or handle the error using a do-catch block.

If a function or method that can throw an error is called without using try or handling the error, Swift will produce a compile-time error with the message "Call can throw, but it is not marked with 'try' and the error is not handled".

Handling errors properly is important to ensure that our code is robust and can handle unexpected situations. We should always handle errors using a do-catch block or propagate them to the caller if they cannot be handled at the current level.

Updated on: 04-May-2023

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements