Error decoding parse-server response

I’m playing around with ParseSwift and a local Parse Server (4.5.0). Whenever I try to perform a query or saving an object to the server I get the error below. Not sure what I’m doing wrong…

ParseError code=-1 error=Error decoding parse-server response: Optional(<NSHTTPURLResponse: 0x600003071700> { URL: http://0.0.0.0:4040//classes/Link } { Status Code: 404, Headers {
    Connection =     (
        "keep-alive"
    );
    "Content-Length" =     (
        153
    );
    "Content-Security-Policy" =     (
        "default-src 'none'"
    );
    "Content-Type" =     (
        "text/html; charset=utf-8"
    );
    Date =     (
        "Sun, 14 Mar 2021 13:20:46 GMT"
    );
    "Keep-Alive" =     (
        "timeout=5"
    );
    "X-Content-Type-Options" =     (
        nosniff
    );
    "X-Powered-By" =     (
        Express
    );
} }) with error: The data couldn’t be read because it isn’t in the correct format.

My Link object:

struct Link: ParseObject {
        var objectId: String?
        var createdAt: Date?
        var updatedAt: Date?
        var ACL: ParseACL?
        var title: String?
    }

This is my query:

func myQuery() {
        let query = Link.query()
        query.find(callbackQueue: .main) { results in
            switch results {
            case .success(let links):
                links.forEach { link in
                    print("Found link: \(link)")
                }
                
            case .failure(let error):
                print("Error: \(error.localizedDescription)")
            }
        }
    }

Can you share some sample code along with the ParseObject you are trying to save/query? We would need to see your Link ParseObject and any ParseObjects it embeds.

Also, do you see errors on the server when saving/querying your object?

Sorry, my bad. Embarrassed to admit I was calling the Dashboard URL instead of the Server API endpoint. Thanks for trying to help!

Well I’m getting the same error trying to User.login() to my Back4app server:

Error logging in: ParseError(code: ParseSwift.ParseError.Code.unknownError, message: "Error decoding parse-server response: Optional(<NSHTTPURLResponse: 0x6000016612c0> { URL: https://parseapi.back4app.com/login } { Status Code: 200, Headers {\n \"Access-Control-Allow-Origin\" = (\n \"*\"\n );\n \"Content-Encoding\" = (\n gzip\n );\n \"Content-Length\" = (\n 221\n );\n \"Content-Type\" = (\n \"application/json; charset=utf-8\"\n );\n Date = (\n \"Sun, 14 Mar 2021 20:50:02 GMT\"\n );\n Etag = (\n \"W/\\\"12b-pwtHiE5t80haWPqUXfiYEXYWIzo\\\"\"\n );\n Server = (\n nginx\n );\n Vary = (\n \"Accept-Encoding\"\n );\n Via = (\n \"1.1 eae631604d5db564451a93106939a61e.cloudfront.net (CloudFront)\"\n );\n \"access-control-allow-credentials\" = (\n true\n );\n \"access-control-allow-headers\" = (\n \"DNT, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, X-Application-ID, X-Access-Token, X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, X-CSRF-Token, X-Parse-Client-Key\"\n );\n \"access-control-allow-methods\" = (\n \"GET, POST, PUT, PATCH, DELETE, OPTIONS\"\n );\n \"access-control-expose-headers\" = (\n \"X-Parse-Job-Status-Id, X-Parse-Push-Status-Id\"\n );\n \"x-amz-cf-id\" = (\n \"ZfKitwBPt93JbhN5v2FYrdbdoQSfI3-zjCEf4kTL5CF-SG5wtKhGmQ==\"\n );\n \"x-amz-cf-pop\" = (\n \"YUL62-C1\"\n );\n \"x-cache\" = (\n \"Miss from cloudfront\"\n );\n \"x-content-type-options\" = (\n nosniff\n );\n \"x-frame-options\" = (\n SAMEORIGIN\n );\n \"x-powered-by\" = (\n Express\n );\n \"x-xss-protection\" = (\n \"1; mode=block\"\n );\n} }) with error: The data couldn’t be read because it isn’t in the correct format.")

I double checked that I am not using the dashboard URL :blush: By the details, it returns HTTP 200, which means non error.

I’ve been able to save an Installation record (without login in). Updating it fails with the same error :confused:

I tried version 4.2 and version 4.4.0 of the server to no avail. Hints?

Can you share the code for your User ParseObject and any ParseObjects it embeds. Also, can you share how you are logging in?

When testing, you should connect your Swift Playground code (3 and 4 are relevant to your issue):

You can set the settings for your server in here:

If the playgrounds work with your server, then you most likely have something wrong in your User struct or your code and should compare it to the ones in Playgrounds.

I’ve initialized it properly since the Install data got written.

Here’s my User struct:

struct PKUser: ParseUser {
    //: These are required for `ParseObject`.
    var objectId: String?
    var createdAt: Date?
    var updatedAt: Date?
    var ACL: ParseACL?

    //: These are required for `ParseUser`.
    var username: String?
    var email: String?
    var password: String?
    var authData: [String: [String: String]?]?
}

I’m digging into the Parse-Swift code. The server response data is:

{
  "objectId": "siQS1p3rUw",
  "emailVerified": true,
  "username": "plbeaudoin",
  "createdAt": "2021-03-14T02:24:47.841Z",
  "updatedAt": "2021-03-14T02:24:52.417Z",
  "email": "[email protected]",
  "ACL": {
    "*": {
      "read": true
    },
    "siQS1p3rUw": {
      "read": true,
      "write": true
    }
  },
  "sessionToken": "r:REDACTED"
}

and the JSONDecode error is:

typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "createdAt", intValue: nil)], debugDescription: "Expected to decode Dictionary<String, Any> but found a string/data instead.", underlyingError: nil))

I’m still trying to understand the error :grin:

The server response looks fine. What version of Parse-Swift are you using?

Did the SDK give you that decoder error, or did you decode that with something else?

I’m using ParseSwift (1.1.6) (from Cocopods).

I’ve gotten this decoding error message by adding a do {} catch {} around line 197 in ParseUser.swift. Without it, I only get the error in my first message in this thread.

Parse dates have a particular date strategy that needs to be set on the encoder/decoder, so you shouldn’t use your own. Instead, try something User().getDecoder().decode(...) if you are debugging.

I recommend setting a breakpoint at line 197 as you mentioned. In the console log winder type po try ParseCoding.jsonDecoder().decode(AnyCodable.self, from: data) and post your output. It should look similar to your server response above, but something seems weird about the dates.

Then try the original line, po try ParseCoding.jsonDecoder().decode(LoginSignupResponse.self, from: data). Does it give you an error? It may be the next line that’s giving you and issue when it attempts to decode as your user type. Try, po try ParseCoding.jsonDecoder().decode(Self.self, from: data)

In addition, try the playgrounds method I mentioned because if it works, we can rule out the SDK and the Server, leaving the issue to your implementation.

Here we go:

(lldb)  po try ParseCoding.jsonDecoder().decode(AnyCodable.self, from: data)
▿ AnyCodable(["ACL": ["*": ["read": true], "siQS1p3rUw": ["read": true, "write": true]], "updatedAt": "2021-03-14T02:24:52.417Z", "createdAt": "2021-03-14T02:24:47.841Z", "emailVerified": true, "email": "[email protected]", "sessionToken": "r:REDACTED", "objectId": "siQS1p3rUw", "username": "plbeaudoin"])
  - dateEncodingStrategy : nil
  ▿ value : 8 elements
    ▿ 0 : 2 elements
      - key : "ACL"
      ▿ value : 2 elements
        ▿ 0 : 2 elements
          - key : "*"
          ▿ value : 1 element
            ▿ 0 : 2 elements
              - key : "read"
              - value : true
        ▿ 1 : 2 elements
          - key : "siQS1p3rUw"
          ▿ value : 2 elements
            ▿ 0 : 2 elements
              - key : "read"
              - value : true
            ▿ 1 : 2 elements
              - key : "write"
              - value : true
    ▿ 1 : 2 elements
      - key : "updatedAt"
      - value : "2021-03-14T02:24:52.417Z"
    ▿ 2 : 2 elements
      - key : "createdAt"
      - value : "2021-03-14T02:24:47.841Z"
    ▿ 3 : 2 elements
      - key : "emailVerified"
      - value : true
    ▿ 4 : 2 elements
      - key : "email"
      - value : "[email protected]"
    ▿ 5 : 2 elements
      - key : "sessionToken"
      - value : "r:228369aec37a5b09560df3931cb8b0b7"
    ▿ 6 : 2 elements
      - key : "objectId"
      - value : "siQS1p3rUw"
    ▿ 7 : 2 elements
      - key : "username"
      - value : "plbeaudoin"

Where

po try ParseCoding.jsonDecoder().decode(LoginSignupResponse.self, from: data)

gives me the error I got by adding the do/catch around line 197:

▿ DecodingError
  ▿ typeMismatch : 2 elements
    - .0 : Swift.Dictionary<Swift.String, Any>
    ▿ .1 : Context
      ▿ codingPath : 1 element
        - 0 : CodingKeys(stringValue: "createdAt", intValue: nil)
      - debugDescription : "Expected to decode Dictionary<String, Any> but found a string/data instead."
      - underlyingError : nil

I’ll look into starting the docker server.

Actually, something is wrong with the way the server is dishing the date. It should look like:

{\"sessionToken\":\"myToken\",\"username\":\"hello10\",\"objectId\":\"yarr\",\"updatedAt\":{\"__type\":\"Date\",\"iso\":\"2021-03-14T18:04:20.485Z\"},\"email\":\"[email protected]\",\"createdAt\":{\"__type\":\"Date\",\"iso\":\"2021-03-14T18:04:20.485Z\"},\"customKey\":\"blah\"

Your date doesn’t have the iso info. At that same breakpoint can you post the output for po String(data: data, encoding: .utf8)?

@davimacedo does the back4app server do anything particular with dates? The Parse-Swift SDK is expecting to see \"__type\":\"Date\",\"iso\":\"2021-03-14T18:04:20.485Z\"

Indeed the dates are not Dictionary<String, Any> but String/data instead!

"createdAt": "2021-03-14T02:24:47.841Z",
"updatedAt": "2021-03-14T02:24:52.417Z",

Yup, the standard Parse Server dishes dates which look like: \"createdAt\":{\"__type\":\"Date\",\"iso\":\"2021-03-14T18:04:20.485Z\" which is what ParseSwift is expecting to decode.

Lets wait for @davimacedo he probably knows why this is happening and how to fix it. I suspect it’s a setting on the server side.

1 Like

@pierlux Can you post the full output from po String(data: data, encoding: .utf8) at the breakpoint?

Sure:

po String(data: data, encoding: .utf8)
▿ Optional<String>
  - some : "{\"objectId\":\"siQS1p3rUw\",\"emailVerified\":true,\"username\":\"plbeaudoin\",\"createdAt\":\"2021-03-14T02:24:47.841Z\",\"updatedAt\":\"2021-03-14T02:24:52.417Z\",\"email\":\"[email protected]\",\"ACL\":{\"*\":{\"read\":true},\"siQS1p3rUw\":{\"read\":true,\"write\":true}},\"sessionToken\":\"r:REDACTED\"}"

Just some more info on what ParseSwift expects to see, it uses the REST API (if you see something in your back4app settings that says “enable for REST”, “use REST endpoints”, or something similar, that may help). Here is the documentation that talks about the date for REST in Parse Server REST API Guide | Parse

Can you set a breakpoint here and let me know what happens. It should still be able to parse the String unless there’s something up with the format

Sure.

decodedString = "2021-03-14T02:24:47.841Z"	

but then the dateFormatter chokes on it and it trows on line 74.

Update: decoding the string date should still work. I added a test here:

Something is up with that particular day/time. When I use the date string you give me it fails (just like you are getting). If I switch the day or year by 1, it passes.

Maybe it has something to do with daylight savings time where I’m at? (this doesn’t make sense to me), but I’m not sure what the problem could be. Maybe something with the timezone or needing to be set to something like UTC.