JSON Error trying to PUT doc via Sync Gateway API

I have a VM running Couchbase Community Edition 7.1.0 build 2556 and Sync Gateway/2.8.2(1;4df7a2d) CE.

I’ve set up a database called “licensees” that maps to “bucket-licensees” which currently is empty (dropped and created).

If I try to add a document to it using the REST API via curl, it is giving me an error “Bad JSON: EOF”. When I look this error up, most of what I found suggests that there’s a syntax error in my JSON file. I originally tried with a document retrieved from another databases and just tried to PUT it without modifying anything. Then I tried this simple doc:

{
  "really": "yes",
  "test": true
}

Command line:

curl -Ss -u 'mike.totman@safedoorpm.com:...' -H "accept: application/json" -H "Content-Type: application/json" -X PUT "http://localhost:4985/licensees/test" --data-binary @~/tmp/test.json

It still fails. I even checked to make sure that the file wasn’t encoded weirdly:

$ file -i test.json 
test.json: text/plain; charset=us-ascii

I’ve tried --data-binary, --data-ascii, --data, it always fails.

If I include the document contents on the command line (e.g. ... -d '{ "really":"yes","test":true}' ) it works
Here’s the secton of the Sync Gateway config file that defines the database:

    "licensees": {
      "server": "couchbase://127.0.0.1",
      "username": "Administrator",
      "password": ".",
      "bucket": "bucket-licensees",
      "enable_shared_bucket_access": true,
      "import_docs": true,
      "users": {
        "GUEST": { "disabled":true, "admin_channels":["*"] },
        "admin": { "password":"...", "admin_channels":["channel-licensees"], "disabled":false },
        "mike.totman@safedoorpm.com": { "password":"...", "admin_channels":["channel-licensees"], "disabled":false }
      },
      "sync": `function(doc, oldDoc) {
                requireAccess("channel-licensees");
                channel("channel-licensees");
              }`,
      "allow_conflicts": false,
      "revs_limit": 20,
      "num_index_replicas": 0
    },

And, for completeness, here’s the bucket config:

I’m at a loss as to why this won’t work.

I tried this as an experiment and didn’t run into any issues. However I got a slightly different output from file

$ file -i test.json
test.json: application/json; charset=us-ascii

Perhaps you’ve put in some odd invisible characters by mistake? Here are the contents of my file:

00000000  7b 0a 20 20 22 72 65 61  6c 6c 79 22 3a 20 22 79  |{.  "really": "y|
00000010  65 73 22 2c 0a 20 20 22  74 65 73 74 22 3a 20 74  |es",.  "test": t|
00000020  72 75 65 0a 7d 0a                                 |rue.}.|
00000026

I don’t see any improper characters:

dev@sdpm-dev-vm:~/tmp$ hexdump -C test.json
00000000  7b 0a 20 20 22 72 65 61  6c 6c 79 22 3a 20 22 79  |{.  "really": "y|
00000010  65 73 22 2c 0a 20 20 22  74 65 73 74 22 3a 20 74  |es",.  "test": t|
00000020  72 75 65 0a 7d 0a                                 |rue.}.|

I had it working before, I’m not sure what changed, unless it’s the recent upgrade of Couchbase. I think I started on 7.0.

I can’t reproduce this issue either. Running on Couchbase Server 7.1 like you and the exact same curl command.

Can you run curl with the -v flag, and paste the output? That should show the file size curl is attempting to send. If I specify a non-existent file, I do get an EOF error, because curl is trying to send a 0 byte JSON doc.

$ curl -v -Ss -u 'Administrator:password' -H "accept: application/json" -H "Content-Type: application/json" -X PUT "http://localhost:4985/db1/test" --data-binary @/tmp/doc2.json
*   Trying 127.0.0.1:4985...
* Connected to localhost (127.0.0.1) port 4985 (#0)
* Server auth using Basic with user 'Administrator'
> PUT /db1/test HTTP/1.1
> Host: localhost:4985
> Authorization: Basic QWRtaW5pc3RyYXRvcjpwYXNzd29yZA==
> User-Agent: curl/7.79.1
> accept: application/json
> Content-Type: application/json
> Content-Length: 0
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request
< Content-Type: application/json
< Server: Couchbase Sync Gateway/3.1 branch/ commit/ CE
< Date: Wed, 25 May 2022 10:02:51 GMT
< Content-Length: 48
<
* Connection #0 to host localhost left intact
{"error":"Bad Request","reason":"Bad JSON: EOF"}%

My file output below might be slightly different being on macOS, but yours (along with the hexdump) looks like it should be working fine.

$ file /tmp/doc.json
/tmp/doc.json: JSON data

$ file -i /tmp/doc.json
/tmp/doc.json: regular file

$ curl -Ss -u 'Administrator:password' -H "accept: application/json" -H "Content-Type: application/json" -X PUT "http://localhost:4985/db1/test" --data-binary @/tmp/doc.json
{"id":"test","ok":true,"rev":"1-946259c2b03803603b862e2646598cb8"}

I’m able to reproduce it on another server where I’m sure it used to work.

Here’s the -v output:

$ curl -vkgSs -u "mike.totman@safedoorpm.com:..." -H "content-type: application/json" -H "accept: application/json" -X PUT https://localhost:4984/licensees/t-dock-test --data-binary @ ~/tmp/t-dock.json
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4984 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Client hello (1):
* TLSv1.3 (OUT), TLS Unknown, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=safedoorpm.com
*  start date: Apr 13 23:42:57 2022 GMT
*  expire date: Jul 12 23:42:56 2022 GMT
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* Server auth using Basic with user 'mike.totman@safedoorpm.com'
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
> PUT /licensees/t-dock-test HTTP/1.1
> Host: localhost:4984
> Authorization: Basic bWlrZS50b3RtYW5Ac2FmZWRvb3JwbS5jb206cGFzc3dvcmQ=
> User-Agent: curl/7.58.0
> content-type: application/json
> accept: application/json
> Content-Length: 0
>
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
< HTTP/1.1 400 Bad Request
< Content-Type: application/json
< Server: Couchbase Sync Gateway/2.8.2 CE
< Date: Wed, 25 May 2022 21:02:30 GMT
< Content-Length: 48
* HTTP error before end of send, stop sending
<
* Closing connection 0
* TLSv1.3 (OUT), TLS Unknown, Unknown (21):
* TLSv1.3 (OUT), TLS alert, Client hello (1):
{"error":"Bad Request","reason":"Bad JSON: EOF"}* <url> malformed
* Closing connection -1
curl: (3) <url> malformed

I’m thinking this has nothing to do with CB/SG and I’ve got something changed in my systems, possibly with curl since it is what is complaining about the URL or contents (HTTP error before end of send, stop sending).

UGH, so stupid. curl didn’t like the ~ at the start of the filename after the @! When I put the full path (or a relative path) there, it worked. Grrrrrrr. :face_with_symbols_over_mouth:

More accurately, it’s when I added the -g parameter to my command-line, which prevents “globbing”, which is the part of the process that would substitute the home directory in place of the ~. Gorram it. PEBKAC.

1 Like

Well, this is all just retrospective now but I’d like to add that the problem that stuck out to me was even before what you had mentioned.

> User-Agent: curl/7.58.0
> content-type: application/json
> accept: application/json
> Content-Length: 0

Notice the content length of 0, which makes sense if it wasn’t actually getting the file