ParseError code=-1 error=Invalid struct: No value associated with key CodingKeys(stringValue: "objectId", intValue: nil) ("objectId")

Hello,
I am getting an error when saving the object. Mind you it still saves it to the parse server, but the persistent error is annoying. I am unable to reproduce this error using any other struct other than my message struct:

ParseError code=-1 error=Invalid struct: No value associated with key CodingKeys(stringValue: “objectId”, intValue: nil) (“objectId”)

This is the struct:

struct Message: ParseObject {
    var originalData: Data?
    
    var objectId: String?
    var createdAt: Date?
    var updatedAt: Date?
    var ACL: ParseACL?
    
    var text: String?
    var time: Date?
    var read: Bool?
    var senderName: String?
    var senderID: String?
    var spouseID: String?
    var chatKey: String?
    
    static func sampleMessage() -> Message {
        return Message(text: "wow this is a sample messag", time: Date(), read: false, senderID: "b", spouseID: "a")
    }
}

This is all I am trying to do:

let sentMessage = Message(text: text, time: Date(), read: false, senderName: usersProfile.name, senderID: usersProfile.id, spouseID: spouse?.id ?? "", chatKey: finalChatID)

sentMessage.save { result in
                    switch result {
                        
                    case .success(_):
                        print("Saved Message")
                    case .failure(let error):
                        print(error)
                        print(error.message)
                    }
                    
                }

Subsequent error messages:

ParseError code=-1 error=Invalid struct: No value associated with key CodingKeys(stringValue: "objectId", intValue: nil) ("objectId").
Invalid struct: No value associated with key CodingKeys(stringValue: "objectId", intValue: nil) ("objectId").

One last observation is that when I refactored it to “Massage”, magically no error. Is there some sort of Message struct that already exists within that is causing this error?

ParseSwift Version: 4.2.0
Parse Server: 4.5
DB: MongoDB 3.6
Xcode: 13.2.1
MacOS: 12.3

I tried your code and unfortunately couldn’t replicate the error.

The only changes I made were supplying default texts to your String? properties.

Just to make it clear, You’re saying “Saved Message” doesn’t print and instead the ParseError ?

do you have any extension to the Message struct maybe somewhere you forgot about? maybe a thirdparty library you loaded?

Correct I am getting a ParseError (even though it saves to the server successfully). I have a lot of third party libraries but no extensions. I will look through them and get back to you.

This would happen to me when I was using a Struct name Set, Parse Swift couldn’t detect the Set struct and instead was using the class Set.

I resolved it by renaming the struct SetObject and adding static let className: String = "Set"

You can check if there are any conflicts just by using autocompletion.

Screen Shot 2022-03-25 at 11.27.32 am

Our Parse Swift expert @cbaker6 might have some other thoughts

1 Like

do you have CloudCode afterSave(“Message”) by any chance? this seems like a cloud code error.

1 Like

The directions @jayson and @dblythy seem like the right ones to me. There seems to be code missing in the initial question that prevents proper diagnoses; basically there’s something going on in your app/parse-server (not the Swift SDK) that we can’t see.

This can easily be the case if you have dependencies and one of them has a struct or class named Message. If so, @dblythy solution should fix it:

From this trial, it would seem the OS doesn’t have a provided type that conflicts with the Message ParseObject you created:

My guess is you have cloud code somewhere that is manipulating/saving Message and returning it incorrectly to the ParseSwift SDK. It looks like the Cloud Code could be “creating” (.POST) the object, but returning the “saved” (.PUT) version to the SDK, which is what @jayson is saying:

After checking, yes I do. My javascript level is beginner at best here is the cloud code for it:

Parse.Cloud.afterSave('Message', async (request) => {
    const messageQuery = new Parse.Query("Message");
    messageQuery.equalTo('objectId', request.object.id);
    
    const results = await messageQuery.find();
    
    console.log('RESULTS $$: '+results[0].get("senderName"));
    console.log('RESULTS &&: '+results[0].get());
    const query = new Parse.Query(Parse.Installation);
    query.equalTo('profileID',results[0].get("spouseID"));
    
    var dict = {
        'title' : results[0].get("senderName") ,
        'body' : results[0].get("text")
    };
    
    return Parse.Push.send({
        where: query,
        data: {
            alert: dict
        }
    }, { useMasterKey: true });
});

Let me check if this is a notification issue because we never properly setup notifications for the BETA server just for production.

After the 5th attempt Xcode finally showed me another Message exists, but would crash/lock up when jumping to the definition. Anyways I will just rename it and manually set the class for now. Thank you all for your help!

The answer should actually be:

Your cloud code afterSave hook isn’t correct and will cause the exact issue you are getting (the latter part of my earlier comment). You shouldn’t return the result of an attempted push notification in afterSave to the Swift SDK. The docs for Parse.Push.send states:

Type: Promise: A promise that is fulfilled when the push request completes.

If you end up reusing that cloud hook, you will probably run into the same problem. This is most likely the reason why Massage doesn’t have an issue because it doesn’t have a matching afterSave hook. You can test this by commenting out your afterSave Message cloud code and see if the original doesn’t throw an error.

A clash of types will only occur if the compiler can’t determine the correct type which usually occurs if the signatures of the initializers look the same. This doesn’t seem to be your situation as you mentioned Message still saves to the Parse Server on the first try.

1 Like

I am seeing something similar to this.
I have an object that comes in from a LiveQuery.
I pass it to a function that was trying to persist the data.

func passMyObjectAndTakeNote(object: MyParseClass) {
    if let thisObjectId = object.objectId {
        print("\(thisObjectId)") //-> proper objectId prints
        let aCopy = object
        print(aCopy.objectId) //-> prints Optional<String>: nil
   }
}

I just discovered what is going on.
I was reading the documentation and noted the details about custom coding keys. I had neglected to keep objectId, createdAt, and updatedAt in the proper place.

However I am also getting this behavior with another object that does not have custom CodingKeys
The problem was resolved by removing returnCacheDataElseLoad from the ParseSwift initialize method.
Not sure exactly what would cause this problem.

Im just getting something similar as well on my new local development installation where I have a cloud code function calling ANOTHER cloudcode function. I’m still doing testing but is this error you’re getting from a local installation as well?

The error I get on the server is

error: Failed running cloud function testCustom for user XXXXXXXXXX with:
  Input: {}
  Error: {"message":"unauthorized"} {"error":{"message":"unauthorized"},"functionName":"testCustom","params":{},"user":"XXXXXXXXXX"}

but the ParseSwift Error I get is

ParseError code=-1 error=Invalid struct: No value associated with key CodingKeys(stringValue: "result", intValue: nil) ("result")."

I think I may not have installed or fixed my config properly to give proper cloud access to somehow.

This sounds like you cached bad data during a previous situation. In any case, I don’t recommend changing the cache policy when initializing the SDK unless you are setting to the cache policy you want for your whole app. Most of the methods that access the server have the ability to accept options in which you can use to set the cachePolicy for individual calls.

The error message itself looks like a bug on the server-side as the error isn’t in the proper Parse Error format (seems to be missing an error code). The Swift SDK only decodes the specific return type your method is looking for or a ParseError. The error you posted is neither. You can verify with @dblythy if this is the case and open an issue on the parse-server repo if it’s a real issue.

As for why the error is being thrown it looks like a configuration issue on your end.

thanks for the confirmation. That’s what I’ve been going off on. I need to figure out why im “unauthorized”

My intention was to have that be the cache policy for the whole app. My concern is that if I set that, it immediately starts failing, even if I should have valid cached data. Once my app starts, it pulls fresh data and either I update it in my app, or I get the live query updates on that object. For the stuff that might be changed by some other installation I should get notified. I may not be understanding how this caching works, but when that policy is enabled, I get objects back without objectIds from every query except live query.

It sounds like you are doing something incorrectly with the SDK or server. I use the default cache policy in all of my apps that use the Swift SDK and I receive standard and live query updates properly with all of the correct properties properly decoded. The SDK uses Apple’s caching policies directly, so you can look there to choose an appropriate policy for your app. You can see a sample app that does this:

You can test by cloning the Swift SDK and testing the playground files with your server setup. If those work correctly, then that means you are probably doing something wrong in your app.