(Solved) Dropbox API copy throws error 999 - run async?

TLDR:

I keep getting error code 999 on successful and unsuccessful copy actions through the Dropbox API. According to this post on the Dropbox Forums, this error is:

Returned when an asynchronous load is canceled.

I’m running these script actions synchronously. Which leads me to the following question:

Should I be running them asynchronously?
If so, how can I implement the async/await in the script to make it work?

Read below for more details.

Dropbox API calls returning error code 999

I’m working on some scripts that copy certain folders in Dropbox to new locations based on text being parsed in various drafts, and thanks to @sylumer’s wonderful example on the Automators forum of how to make a basic Dropbox API call, I have managed to successfully copy folders on Dropbox through an API call.

However, I keep getting error message 999 from the Dropbox API.

Test Script

This test script actually runs successfully if the folder exist in the source path and not the destination path. I only get the 999 error when the destination folder already exist, and nothing gets copied:

//Create Dropbox object
let dbxMain = Dropbox.create()

//Build some file info
let src = "/0-temp/test/source/testcopy"
let dst = "/0-temp/test/destination/testcopy"

//Build the arguments for calling the Dropbox move
let urlEndpoint = "https://api.dropboxapi.com/2/files/copy_v2";
let dictArgs = {
	"from_path": src,
	"to_path": dst,
	"allow_shared_folder": false,
	"autorename": false,
	"allow_ownership_transfer": false
};

//Move the file
let objResp = dbxMain.rpcRequest(
{
	"url": urlEndpoint,
	"method": "POST",
	"data": dictArgs
});

//Baseline check if it worked
if (objResp.statusCode != 200)
{
	//It didn't :o(
	alert("Dropbox Returned an Error: [" + objResp.statusCode + "] " + objResp.error);
	context.fail();
}
else
{
	//It did :o)
	alert("Success!");
}

Result:

If destination folder exists: // Dropbox Returned an Error: [999]
If destination folder does not exists: // Success!

Actual script

Testing paths in my actual script, I only get 999 errors:

let testPaths = [
  {
    src: "/0-temp/test/src/testcopy1",
    dst: "/0-temp/test/dst/testcopy1"
  },
  {
    src: "/0-temp/test/src/testcopy2",
    dst: "/0-temp/test/dst/testcopy2"
  },
  {
    src: "/0-temp/test/src/testcopy3",
    dst: "/0-temp/test/dst/testcopy3"
  }
];

testPaths.forEach(path => {
  copyFiles(path['src'], path['dst']);
});

function copyFiles(src, dst) {
  //Create Dropbox object
  const dbxMain = Dropbox.create();
  
  //Build the arguments for calling the Dropbox copy
  let urlEndpoint = "https://api.dropboxapi.com/2/files/copy_v2";
  let dictArgs = {
    "from_path": src,
    "to_path": dst,
    "allow_shared_folder": false,
    "autorename": false,
    "allow_ownership_transfer": false
  };
    
  // Move the file
  let objResp = dbxMain.rpcRequest(
      {
        "url": urlEndpoint,
        "method": "POST",
        "data": dictArgs
      });

  //Baseline check if it worked
  if (objResp.statusCode != 200) {
    	alert("Dropbox Returned an Error: [" + objResp.statusCode + "] " + objResp.error);
    	context.fail()
  } 
  else {
    alert("Files copied from: \n" + src + "\n\n" + "to: \n" + dst);
  };

Folder exists in both src and dst // Dropbox Returned an Error: [999]
Folder exists only in src // Dropbox Returned an Error: [999]
Folder does not exist in src // Dropbox Returned an Error: [999]

Before:


After:

As you can see, I get error 999 even when the copy is successful.

Unsuccessful attempt at using asynchronous load

I read the post on Asynchronous scripting in Drafts, and following the link to javascript.info, I tried implementing their example of wrapping the function call in an async function. Did I screw this up?

// Inside the copyFiles function
(async () => {
  let objResp = await dbxMain.rpcRequest(
    {
	   "url": urlEndpoint,
	   "method": "POST",
	   "data": dictArgs
    });
})();
// executing the copyFiles function
testPaths.forEach(path => {
  copyFiles(path['src'], path['dst']);
});
script.complete();

Result

Fail. Drafts never reached script.complete() and timed out.

I’ve run your example several times and only get the error when a folder exists at the destination path…which is expected behavior per the file/copy API docs.

Are you sure you have setup your example files so the destination folders do not exist (and those changes have finished syncing to Dropbox if made locally) before running the script?

You are right, it seems to be working now. I don’t know why I kept getting errors yesterday, maybe as you said Dropbox didn’t synchronize my deletions before I ran the script.

Sorry for wasting your time, thanks for the help!