title: 'InvalidPathValidation' while using Swift 3
body: <p>I have an app that uses Firebase to send and receive messages between users. During the process of updating my code to the new Swift 3 so that I can add the cool new features of iOS 10 to my app, I ran into several errors. I was able to fix the majority of them except this one at runtime:</p>
  
  <pre><code>Terminating app due to uncaught exception 'InvalidPathValidation', reason: '(child:) Must be a non-empty string and not contain '.' '#' '$' '[' or ']''
  </code></pre>
  
  <p>I have no clue what could have caused this. The user's userID gets printed to the console when they are logged in, but yet my app crashes as soon as the log in button is pressed. This error was non-existent before I updated to Swift 3, and actually only appeared after I fixed a bug in another part of my application. </p>
  
  <p>Anyways, I only have two main classes in my application: <code>LoginViewController</code> and <code>ChatViewController</code>.</p>
  
  <p>Here is the code for <code>LoginViewController</code>:</p>
  
  <pre><code>import UIKit
  import Firebase
  
  class LoginViewController: UIViewController {
  
      // MARK: Properties
      var ref: FIRDatabaseReference! // 1
      var userID: String = ""
  
      override func viewDidLoad() {
          super.viewDidLoad()
          ref = FIRDatabase.database().reference() // 2
      }
  
      @IBAction func loginDidTouch(_ sender: AnyObject) {
          FIRAuth.auth()?.signInAnonymously() { (user, error) in
              if let user = user {
                  print("User is signed in with uid: ", user.uid)
                  self.userID = user.uid
              } else {
                  print("No user is signed in.")
              }
  
              self.performSegue(withIdentifier: "LoginToChat", sender: nil)
  
          }
  
      }
  
      override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
          super.prepare(for: segue, sender: sender)
          let navVc = segue.destinationViewController as! UINavigationController // 1
          let chatVc = navVc.viewControllers.first as! ChatViewController // 2
          chatVc.senderId = userID // 3
          chatVc.senderDisplayName = "" // 4
      }
  
  
  }
  </code></pre>
  
  <p>Here is my code for <code>ChatViewController</code>:</p>
  
  <pre><code>import UIKit
  import Firebase
  import JSQMessagesViewController
  
  class ChatViewController: JSQMessagesViewController {
  
      // MARK: Properties
  
      var rootRef = FIRDatabase.database().reference()
      var messageRef: FIRDatabaseReference!
  
      var messages = [JSQMessage]()
      var outgoingBubbleImageView: JSQMessagesBubbleImage!
      var incomingBubbleImageView: JSQMessagesBubbleImage!
  
      var userIsTypingRef: FIRDatabaseReference! // 1
      private var localTyping = false // 2
      var isTyping: Bool {
          get {
              return localTyping
          }
          set {
              // 3
              localTyping = newValue
              userIsTypingRef.setValue(newValue)
          }
      }
      var usersTypingQuery: FIRDatabaseQuery!
  
  
      override func viewDidLoad() {
          super.viewDidLoad()
          title = "ChatChat"
          setupBubbles()
          // No avatars
          collectionView!.collectionViewLayout.incomingAvatarViewSize = CGSize.zero
          collectionView!.collectionViewLayout.outgoingAvatarViewSize = CGSize.zero
          messageRef = rootRef.child("messages")
      }
  
      override func viewDidAppear(_ animated: Bool) {
          super.viewDidAppear(animated)
          observeMessages()
          observeTyping()
      }
  
      override func viewDidDisappear(_ animated: Bool) {
          super.viewDidDisappear(animated)
      }
  
  
      func collectionView(collectionView: JSQMessagesCollectionView!,
                                   messageDataForItemAtIndexPath indexPath: NSIndexPath!) -&gt; JSQMessageData! {
          return messages[indexPath.item]
      }
  
      func collectionView(collectionView: JSQMessagesCollectionView!,
                                   messageBubbleImageDataForItemAtIndexPath indexPath: NSIndexPath!) -&gt; JSQMessageBubbleImageDataSource! {
          let message = messages[indexPath.item] // 1
          if message.senderId == senderId { // 2
              return outgoingBubbleImageView
          } else { // 3
              return incomingBubbleImageView
          }
      }
  
      override func collectionView(_ collectionView: UICollectionView,
                                   numberOfItemsInSection section: Int) -&gt; Int {
          return messages.count
      }
  
      func collectionView(collectionView: JSQMessagesCollectionView!,
                                   avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -&gt; JSQMessageAvatarImageDataSource! {
          return nil
      }
  
      private func setupBubbles() {
          let factory = JSQMessagesBubbleImageFactory()
          outgoingBubbleImageView = factory?.outgoingMessagesBubbleImage(
              with: UIColor.jsq_messageBubbleBlue())
          incomingBubbleImageView = factory?.incomingMessagesBubbleImage(
              with: UIColor.jsq_messageBubbleLightGray())
      }
  
      func addMessage(id: String, text: String) {
          let message = JSQMessage(senderId: id, displayName: "", text: text)
          messages.append(message!)
      }
  
      override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -&gt; UICollectionViewCell{
          let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell
  
          let message = messages[indexPath.item]
  
          if message.senderId == senderId {
              cell.textView!.textColor = UIColor.white()
          } else {
              cell.textView!.textColor = UIColor.black()
          }
  
          return cell
      }
  
      func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!,
                                       senderDisplayName: String!, date: NSDate!) {
  
          let itemRef = messageRef.childByAutoId() // 1
          let messageItem = [ // 2
              "text": text,
              "senderId": senderId
          ]
          itemRef.setValue(messageItem as? AnyObject) // 3
  
          // 4
          JSQSystemSoundPlayer.jsq_playMessageSentSound()
  
          // 5
          finishSendingMessage()
  
          isTyping = false
  
      }
  
      private func observeMessages() {
          // 1
          let messagesQuery = messageRef.queryLimited(toLast: 25)
          // 2
          messagesQuery.observe(.childAdded) { (snapshot: FIRDataSnapshot!) in
              // 3
              let id = snapshot.value!["senderId"] as! String
              let text = snapshot.value!["text"] as! String
  
              // 4
              self.addMessage(id: id, text: text)
  
              // 5
              self.finishReceivingMessage()
          }
      }
  
      private func observeTyping() {
          let typingIndicatorRef = rootRef.child("typingIndicator")
          userIsTypingRef = typingIndicatorRef.child(senderId)
          userIsTypingRef.onDisconnectRemoveValue()
  
          // 1
          usersTypingQuery = typingIndicatorRef.queryOrderedByValue().queryEqual(toValue: true)
  
          // 2
          usersTypingQuery.observe(.value) { (data: FIRDataSnapshot!) in
  
              // 3 You're the only typing, don't show the indicator
              if data.childrenCount == 1 &amp;&amp; self.isTyping {
                  return
              }
  
              // 4 Are there others typing?
              self.showTypingIndicator = data.childrenCount &gt; 0
              self.scrollToBottom(animated: true)
          }
      }
  
      override func textViewDidChange(_ textView: UITextView) {
          super.textViewDidChange(textView)
          // If the text is not empty, the user is typing
          isTyping = textView.text != ""
      }
  
      func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForCellBottomLabelAtIndexPath indexPath: NSIndexPath!) -&gt; AttributedString! {
          return AttributedString(string:"test")
      }
  
  }
  </code></pre>
  
  <p>Mind, all of this code is written in Swift 3.</p>
  
  <p>If you can find anything that will help me fix my problem and finally get my app to work, I will be your best friend.</p>
  
  <p>Thanks in advance!</p>