101
Alamofire.request(.GET, "url").authenticate(user: "", password: "").responseJSON() {
    (request, response, json, error) in
    println(error)
    println(json)

}

This is my request with Alamofire, for a certain request it sometime works, but sometimes i get:

Optional(Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Invalid value around character 0.) UserInfo=0x78e74b80 {NSDebugDescription=Invalid value around character 0.})

I've read that this can be due to invalid JSON, but the response is a static json string that i have validated in JSON validator as valid. It does contain å ä ö characters and some HTML.

Why am i getting this error sometimes?

Lord Vermillion
  • 5,264
  • 20
  • 69
  • 109

21 Answers21

153

I also faced same issue. I tried responseString instead of responseJSON and it worked. I guess this is a bug in Alamofire with using it with django.

Lukas Würzburger
  • 6,543
  • 7
  • 41
  • 75
Smit
  • 1,696
  • 1
  • 14
  • 17
  • 3
    Thanks for pointing that out. I was using responseJSON but the actual response from the server was in XML format! Saved me the headache :) – C0D3 Dec 07 '15 at 22:43
  • saved my project after hours facing this problem.I should set response in JSON format within my server. I was not doing this, but once I did, I could use responseJSON from alamofire – guijob Dec 14 '16 at 22:16
  • If you are using GET then you need to check with responseString only otherwise for POST check it using responseJSON. Reference: https://grokswift.com/updating-alamofire-to-swift-3-0/ – Anurag Sharma Jan 27 '17 at 05:21
  • I lost customers because of this issue in my iOS app. – Jaseem Abbas Mar 21 '17 at 09:44
  • @Smit Thakkar how would you parse the json response from the string?, i´m receiving this response but i cannot use responseJSON due to the html error message but i need to process the json anyways "
    \nNotice: Undefined offset: 0 in server/file on line 357
    \n
    \nNotice: Undefined offset: 0 in server/file on line 358
    \n{\"status\":\"success\",\"desc\":\"all proceed",\"data\":[{\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJyZW50aS5teCIsImF1ZCI6Imh0dHBzOlwvXC9yZW50aS5teCIsImlhdCI6MTQ5MzYwMzY2MCwiZXhwIjox\"}]}"
    – Cesar Mtz May 01 '17 at 01:56
  • 1
    Your response is messed up with html, you need to parse the html and get the json string out and convert it to dictionary. I recommend trying out SwiftSoup or for better alternatives to parseHtml look at http://stackoverflow.com/questions/31080818/what-is-the-best-practice-to-parse-html-in-swift. – Smit May 01 '17 at 04:34
  • making above change again returning this error `The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable.` while it is wokring well on `Postman` – Vaibhav Saran Aug 27 '17 at 17:43
  • @VaibhavSaran can you put the gist of your code snippet and also tell me the status code that you are getting. – Smit Nov 06 '17 at 12:56
  • Authorization is need to apply forcefully then you dont need to change it to "responcestring" Keep responseJSON as it is. – Yogesh Dalavi Dec 26 '18 at 12:27
  • THANK YOU! This was exactly what I needed! – lizziepika Mar 07 '19 at 00:36
11

In my case , my server URL was incorrect. Check your server URL !!

Saeed
  • 3,415
  • 3
  • 24
  • 41
  • This was the issue for me. I can't believe I missed it. I have to make a habit of checking the URL first, and always! – LondonGuy Jun 16 '20 at 19:51
9

I got same error while uploading image in multipart form in Alamofire as i was using

multipartFormData.appendBodyPart(data: image1Data, name: "file")

i fixed by replacing by

multipartFormData.appendBodyPart(data: image1Data, name: "file", fileName: "myImage.png", mimeType: "image/png")

Hope this help someone.

Avijit Nagare
  • 8,482
  • 7
  • 39
  • 68
  • I had hours trying to figure this out. I wonder why this solution works... Thank you! – MVZ Oct 10 '16 at 20:18
8

May this Help YOu

Alamofire.request(.GET, "YOUR_URL")
     .validate()
     .responseString { response in
         print("Success: \(response.result.isSuccess)")
         print("Response String: \(response.result.value)")
     }
Krutarth Patel
  • 3,407
  • 6
  • 27
  • 54
7

The same issue happened to me and it actually ended up being a server issue since the content type wasn't set.

Adding

.validate(contentType: ["application/json"])

To the request chain solved it for me

Alamofire.request(.GET, "url")
        .validate(contentType: ["application/json"])
        .authenticate(user: "", password: "")
        .responseJSON() { response in
            switch response.result {
            case .Success:
                print("It worked!")
                print(response.result.value)
            case .Failure(let error):
                print(error)
            }
        }
cameronmoreau
  • 407
  • 1
  • 6
  • 14
4

I got the same error. But i found the solution for it.

NOTE 1: "It is not Alarmofire error", it's bcouse of server error.

NOTE 2: You don't need to change "responseJSON" to "responseString".

public func fetchDataFromServerUsingXWWWFormUrlencoded(parameter:NSDictionary, completionHandler: @escaping (_ result:NSDictionary) -> Void) -> Void {

        let headers = ["Content-Type": "application/x-www-form-urlencoded"]
        let completeURL = "http://the_complete_url_here"
        Alamofire.request(completeURL, method: .post, parameters: (parameter as! Parameters), encoding: URLEncoding.default, headers: headers).responseJSON { response in

            if let JSON = response.result.value {
                print("JSON: \(JSON)") // your JSONResponse result
                completionHandler(JSON as! NSDictionary)
            }
            else {
                print(response.result.error!)
            }
        }
    }
Ram Madhavan
  • 2,362
  • 1
  • 17
  • 20
4

This is how I managed to resolve the Invalid 3840 Err.

The error log

 responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
  1. It was with Encoding Type used in the Request, The Encoding Type used should be acceptedin your Server-Side.

In-order to know the Encoding I had to run through all the Encoding Types:

default/ methodDependent/ queryString/ httpBody

    let headers: HTTPHeaders = [
        "Authorization": "Info XXX",
        "Accept": "application/json",
        "Content-Type" :"application/json"
    ]

    let parameters:Parameters = [
        "items": [
                "item1" : value,
                "item2": value,
                "item3" : value
        ]
    ]

    Alamofire.request("URL",method: .post, parameters: parameters,encoding:URLEncoding.queryString, headers: headers).responseJSON { response in
        debugPrint(response)
     }
  1. It also depends upon the response we are recieving use the appropriate
    • responseString
    • responseJSON
    • responseData

If the response is not a JSON & just string in response use responseString

Example: in-case of login/ create token API :

"20dsoqs0287349y4ka85u6f24gmr6pah"

responseString

Ratz
  • 109
  • 1
  • 7
3

I solved using this as header:

let header = ["Content-Type": "application/json", "accept": "application/json"]

Bruno Muniz
  • 316
  • 3
  • 17
2

In my case, there was an extra / in the URL .

Alok
  • 266
  • 2
  • 11
1

Maybe it is too late but I solved this problem in another way not mentioned here:

When you use .responseJSON(), you must set the response header with content-type = application/json, if not, it'll crash even if your body is a valid JSON. So, maybe your response header are empty or using another content-type.

Make sure your response header is set with content-type = application/json to .responseJSON() in Alamofire work properly.

guijob
  • 4,413
  • 3
  • 20
  • 39
1

Hey guys this is what I found to be my issue: I was calling Alamofire via a function to Authenticate Users: I used the function "Login User" With the parameters that would be called from the "body"(email: String, password: String) That would be passed

my errr was exactly:

optional(alamofire.aferror.responseserializationfailed(alamofire.aferror.responseserializationfailurereason.jsonserializationfailed(error domain=nscocoaerrordomain code=3840 "invalid value around character 0." userinfo={nsdebugdescription=invalid value around character 0

character 0 is the key here: meaning the the call for the "email" was not matching the parameters: See the code below

func loginUser(email: String, password: String, completed: @escaping downloadComplete) { let lowerCasedEmail = email.lowercased()

    let header = [
        "Content-Type" : "application/json; charset=utf-8"
    ]
    let body: [String: Any] = [
        "email": lowerCasedEmail,
        "password": password
    ]

    Alamofire.request(LOGIN_USER, method: .post, parameters: body, encoding: JSONEncoding.default, headers: header).responseJSON { (response) in
        if response.result.error == nil {

            if let data = response.result.value as? Dictionary<String, AnyObject> {
                if let email = data["user"] as? String {
                    self.userEmail = email
                    print(self.userEmail)
                }
                if let token = data["token"] as? String {
                    self.token_Key = token
                    print(self.token_Key)
                }

"email" in function parameters must match the let "email" when parsing then it will work..I no longer got the error...And character 0 was the "email" in the "body" parameter for the Alamofire request:

Hope this helps

berkat0789
  • 51
  • 3
1

I was sending the improper type (String) to the server in my parameters (needed to be an Int).

agrippa
  • 819
  • 10
  • 8
1

Error was resolved after adding encoding: JSONEncoding.default with Alamofire.

  Alamofire.request(urlString, method: .post, parameters: 
  parameters,encoding: 
  JSONEncoding.default, headers: nil).responseJSON {  
   response in
   switch response.result {
                   case .success:
                    print(response)
                    break

                    case .failure(let error):
                     print(error)
        }
   }
krishnan muthiah pillai
  • 2,711
  • 2
  • 29
  • 35
0

The application I was working on this morning had the same error. I believed it to be a server side error since I was unable to upload a user image.

However, upon checking my custom API, I realized that after adding an SSL certificate to my website that I had not updated the api.swift URLs, the data was unable to post:

let HOME_URL = "http://sitename.io"
let BASE_URL = "http://sitename.io/api"
let UPLOAD_URL = "http://sitename.io/api/user/upload"

I changed the URL's to https://. Problem solved.

Noble Polygon
  • 796
  • 11
  • 36
0

In my case I have to add this Key: "Accept":"application/json" to my header request.

Something like this:

let Auth_header: [String:String] = ["Accept":"application/json", "Content-Type" : "application/json", "Authorization":"Bearer MyToken"]

I hope that this can help someone.

Dasoga
  • 5,489
  • 4
  • 33
  • 40
0

I face same issue and problem is in params.

let params = [kService: service,
                  kUserPath: companyModal.directory_path,
                  kCompanyDomain: UserDefaults.companyDomain,
                  kImageObject: imageString,
                  kEntryArray: jsonString,
                  kUserToken:  UserDefaults.authToken] as [String : Any]

companyModal.directory_path is url. it coerced from string to any which create issues at server side. To resolve this issue I have to give default value which make it string value.

 let params = [kService: kGetSingleEntry,
                  kUserPath: companyModal.directory_path ?? "",
                  kCompanyDomain: UserDefaults.companyDomain,
                  kUserToken: UserDefaults.authToken,
                  kEntryId: id,
                  ] as [String: Any]
Hitesh Agarwal
  • 1,943
  • 17
  • 21
0

Probably you have "/" at the end of your path. If it is not GET request, you shouldn't put "/" at the end, otherwise you'll get the error

Mark Darry
  • 27
  • 7
0

I Changed mimeType from "mov" to "multipart/form-data".

Alamofire.upload(multipartFormData: { (multipartFormData) in
            do {
                let data = try Data(contentsOf: videoUrl, options: .mappedIfSafe)
                let fileName = String(format: "ios-video_%@.mov ", profileID)
                multipartFormData.append(data, withName: "video", fileName: fileName, mimeType: "multipart/form-data")

            } catch  {
                completion("Error")
            }
        }, usingThreshold: .init(), to: url,
           method: .put,
           headers: header)

Worked for me.. :)

K Ravi Kumar
  • 71
  • 1
  • 2
0

For my case:

let header = ["Authorization": "Bearer \(Authserices.instance.tokenid)"]

I forgot the space before \ (after Bearer)

Studocwho
  • 2,404
  • 3
  • 23
  • 29
haggag
  • 1
  • 2
0

In my case error was due to duplicate email. You can recheck your API on postman to see if response there is OK or not.

Arqam Butt
  • 31
  • 1
0

In my case, I tried using Postman to get API and this error come from backend.