1

I have a function to fetch convos and it worked but then I deleted all the documents in Firebase. So now when I run it, it says "document path cannot be empty" and the app crashes. I am not very familiar with Swift but in Python I simply just use a try and except.

In the try block I can simply copy and paste all my code, and the except block I just do my error handling. I'm not sure how to do this in Swift for my entire function. How can I rearrange my function so that the function body is inside a do/try block?

Also what is the most strategic spot to do my error handling, the viewModel file or the Service file? The viewModel file inherits functions from the service file.

viewModel file:

 func fetchConvos(){ var userList: [User] = [] service.getConversations() { users in userList = users userList.forEach { user in var messList: [Message] = [] } } } 

service file:

 func getConversations(completion: @escaping([User]) -> Void){ Firestore.firestore().collection("users") .document(uid) .collection("user-convo") .getDocuments { snapshot, _ in guard let documents = snapshot?.documents else { return } documents.forEach { doc in let userID = doc.documentID users.append(userID) completion(users) } } } 
7
  • @loremipsum I saw that but wasnt able to fix my code with that, I simply need to use a try except block for each of my functions. Would you know how to do that? Commented Dec 21, 2022 at 3:05
  • 1
    Firebase doesn't provide that, for this error, your uid is more than likely nil you can throw your own error by checking before you put it in the document Firebase is terrible at throwing errors. This isn't a Swift this you are attempting to catch from something that doesn't throw that is an API issue. Commented Dec 21, 2022 at 3:14
  • Something you could try is switching to the async/await methods, there is a little better error handling there. stackoverflow.com/questions/73636543/… Commented Dec 21, 2022 at 3:19
  • @loremipsum so should i try and change up my functions in the service file or viewModel file? or both. Commented Dec 21, 2022 at 3:33
  • Service, once you have it in the service you can use it in the VM Commented Dec 21, 2022 at 3:34

2 Answers 2

0

Trying to handle an exception as flow control is a bad idea here. See for an explanation why that is: Why not use exceptions as regular flow of control?

So instead of handling the exception that you get when uid is null or empty, check whether it has a value first and then only call the Firestore API with it if it has a value. For example:

if !(uid ?? "").isEmpty { Firestore.firestore().collection("users") .document(uid) .collection("user-convo") ... } 

There is no specific operation to check whether a collection exists.

Instead collection is comes into existence when you add the first document to it, and disappears when you remove the last document from it.

So to check whether a collection exists, the simplest way is to try and read a single document from it.

Firestore.firestore().collection("users") .document("theUID") .collection("user-convo") .limit(to: 1) // 👈 .getDocuments { snapshot, _ in if !snapshot!.isEmpty ... // 👈 } 
Sign up to request clarification or add additional context in comments.

5 Comments

in my case the uid is not the issue, the uid already has the right value. Your solution assumes that if there is a uid there is a collection. My problem is that I have a uid and I have to check if there is a collection.
Given the document path cannot be empty, you are passing an empty value to document() somewhere. In the code you shared, the only option for that seems to be the uid. --- I updated my answer to show how to check whether a subcollection exists too.
thanks, if I try and read 1 document from a collection as you modeled above would that still result in the error: "document path cannot be empty" if there is no collection existing for that path.
Basically does your solution above not cause a fatal error if there is no collection existing from which I am calling.
"does your solution above not cause a fatal error if there is no collection" Nope it doesn't, lack of collections never causes an error like that. If you get that error **you are passing an empty value to the document method. There is no other way to get it (and hence me specifying a hardcoded value in my answer). Did you try the code like that, with a hard-coded value - even if that doesn't fit your use-case, it will help in figuring out where the problem comes from.
0

I would avoid "checking" to see if a collection exists or doesn't, unless if there is a good and specific reason to. If there isn't, then simply query the documents you need and if you get them you get them and if you don't you don't; springboard from there.

As to your error, a do-try-catch approach is not the solution I'd use here because that sort of error handling should be reserved for things out of your control, like network tasks. Your specific error is completely in your control because you've constructed an illegal document path. You can, and should, safeguard against this by simply ensuring the strings you pass into the path are valid, which is always best practice if there's a chance they can be nil.

Furthermore, deleting the documents from this collection and the error you're receiving appear to be coincidental, unless if there is code elsewhere that's constructing this document path based on the existence of documents in this collection. If there isn't (and there probably shouldn't) then this is just a coincidence.

1 Comment

what do you mean by "if you get them you get them and if you dont you dont" my initial code doesnt check if a collection exists or not. It simply trys to get the documents from that collection as you said is a better approach. But in doing so I get a fatal error "document path cannot be empty"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.