Potential Channel Access Issue (Push Functioning, Pull Failing)

Hi, I have been successfully using a combination of Couchbase Server with Couchbase Lite/Sync Gateway for Android for about a year now, with a simple sync function JSON that did not utilize any authentication or channels. I am now at the point where it is important to take advantage of that functionality, and I modified your sample code in order to do this (wonderful tutorial, thank you). I am having no problem pushing data to my server, and according to the HTML interface on localhost:4985, my documents are being routed to the proper channels with the proper accesses granted. However, when I push data from device A, and then attempt to pull data on device B I get nothing in return. My hope is that I am simply making a fundamental error in my Sync Function, so I have provided that as my starting point. If you could take a cursory look and let me know if I am making a stupid mistake I would appreciate it greatly. Otherwise, it’s back to the debugging board. Thanks a lot for your help:

  "log": ["*"],
		"users": {
        		"matt": {"password": "test", "admin_channels": ["matt"]},
        		"bryan": {"password": "test", "admin_channels": ["bryan"]},
        		"mod": {"password": "test", "admin_roles": ["moderator"]},
        		"admin": {"password": "test", "admin_roles": ["admin"]}
		"roles": {
        		"moderator": {},
        		"admin": {}
      function(doc, oldDoc) {
			/*Validation that document has a type*/
			if (isCreate()) {
				// Don't allow creating a document without a type.
				validateNotEmpty("documentType", doc.documentType);
			} else if (isUpdate()) {
				// Don't allow changing the type of any document.
				validateReadOnly("documentType", doc.documentType, oldDoc.documentType);
			if (getType() == "numbers") {
    				/* Write access */
				var username = doc._deleted ? oldDoc.username : doc.username
				try {
					// Moderators can create or update lists for other users.
				} catch (e) {
					// Users can create or update lists for themselves.
    				/* Validation */
				if (!isDelete()) {
					// Validate required fields.
					validateNotEmpty("username", doc.username);
					validateNotEmpty("data", doc.data);
					if (isCreate()) {
						// Validate that the _id is prefixed by owner.
						if (!hasPrefix(doc._id, doc.username + ".")) {
							throw({forbidden: "task-list id must be prefixed by list username"});
					} else {
						// Don’t allow task-list ownership to be changed.
						validateReadOnly("username", doc.username, oldDoc.username);

    				/* Routing */
				// Add doc to task-list's channel.
				channel("numbers." + doc._id);
    				/* Read Access */
				// Grant task-list owner access   
				access(username, "numbers." + doc._id);
				access("role:moderator", "numbers." + doc._id);
  			} else {
				// Log invalid document type error.
				log("Invalid document type: " + doc.documentType);

				throw({forbidden: "Invalid document type: " + doc.documentType});

			function getType() {
				return (isDelete() ? oldDoc.documentType : doc.documentType);
			function isCreate() {
				// Checking false for the Admin UI to work
				return ((oldDoc == false) || (oldDoc == null || oldDoc._deleted) && !isDelete());

			function isUpdate() {
				return (!isCreate() && !isDelete());


			function isDelete() {
				return (doc._deleted == true);

			function validateNotEmpty(key, value) {
				if (!value) {
					throw({forbidden: key + " is not provided."});

			function validateReadOnly(name, value, oldValue) {
				if (value != oldValue) {
					throw({forbidden: name + " is read-only."});

			// Checks whether the provided value starts with the specified prefix
			function hasPrefix(value, prefix) {
				if (value && prefix) {
				return value.substring(0, prefix.length) == prefix
				} else {
					return false

do you start pull replication from device B?
can you provide sample document that push from device A,and users on the device A and B?

Yes, I am using a continuous pull replication from device B. Here is what a document looks like on the HTML Sync Gateway Interface:


as your sample document shows, user matt will be able to access document matt.10...702
by channel numbers.matt.10...702

so you can get the data by matt user in device A and device B and Sync Gateway Public REST API,such as

curl -X GET -H "Content-Type:application/json" http://matt:test@


  1. you should login as matt user in device A and device B;
  2. you should start push replication with matt user in device A;
  3. you should start pull replication with matt user in device B;

Thanks atom_yang, unfortunately I have been doing exactly what I should be doing and it is not working. I was hoping I was making a novice mistake, but it appears that there is something more nefarious at work here. I appreciate your input.

may be you can show more details about

so we can find the problem.