Generic Error Handling in SPServices

Recently, I got this question in the SPServices Discussions:

I’m new to SPServices, and I was wondering if it is possible to define some kind of out-of-the-box error handling procedure, like this:

$().SPServices ({
operation: "DoSomething",
[option1: value1],
[option2: value2],
    // ...
success: function (xData) {
        alert ("The operation has been completed!");
        // some processing code ...
    },
fail: function (jqXHR) {
        alert ("Something went wrong!");
        // some fallback code ....
    }
});

The only thing I am aware of is that you can do something like this:

completefunc: function (xData, Status) {
    if (Status == "Success") {
        alert ("The operation has been completed!");
    } else {
        alert ("Something went wrong!");
    }
}

However, this solution will also execute the success-branch when the server returns an XML-document containing error messages. Above that, I don’t think it’s that elegant because you would have to check the Status == “Success” every time you define a new request, which looks a little bit like overkill.

Any suggestions?

By the way: really love this project!

I was on vacation with only my iPhone (my first laptop-free vacation in probably 10 years!) so I waited until I returned to answer. The question is similar to many others I’ve received since I started working on SPServices.

Oh, I’d love to add something like this! Unfortunately, it’s not that simple.

There are two main layers where an error can occur:

  1. In the AJAX call itself. This really only occurs if the endpoint (SharePoint) isn’t responding, almost always due to the servers being down. SOAP may be an old, crufty standard, but it’s damn reliable.
  2. In the Web Service itself. Unfortunately there is almost zero consistency in the implementations. No two operations respond in quite the same way, and there’s really very little in common across the Web Services. Some operations return only one error message regardless what you’ve done wrong, and others return 5 or 6, but inconsistently. Some responses contain heavily nested XML while others contain a single element with many attributes. The only real commonality is that they return XML.

In all of my use of SPServices, I’ve found a few truths.

  1. SharePoint always responds if it’s up and running.
  2. The only time a Web Service call fails is if you pass it bad data or poorly formed XML.
  3. If you get a valid response, then the operation succeeded.

Early on I decided that my job in SPServices is to reduce the likelihood of 2. By eliminating the need to construct the SOAP envelopes, SOAP headers, etc., a huge number of errors simply never happen. It’s up to you to test the XML coming back to see if it contains what you expect.

While I could add error handling for some of the core operations, I would have to assume quite a few things about what you are doing. For instance, you might be calling GetListItems specifically to see if you get zero items back, and that might be a success to you.

What I *have* done is to add the debug mode to many of the “value-added” functions. Because I know what ought to be coming back when I make calls to the various Web Services, I can reasonably provide some error messages that are useful for you to use in setting things up. Things like this debug message:

SPCascadeDropdowns Debug Message Example
Which brings me to another important point: what should we do when there is an error? I’ve vowed to myself never to write an error message like “An error has occurred. Please contact your administrator.” (What error? Is it important? Do I need to do something to fix it? Who’s my administrator? How do I contact them? What do I tell them?) Even something with a correlation ID which can only be deciphered by an administrator is too obtuse. It’s the user who needs to know what to do if there’s a problem.

Given the myriad ways people use SPServices, I can’t possibly predict what they are building or how it should behave. It is first a toolkit and second a power user tool. The core of SPServices should give a developer lean tools that can use how they see fit. Generic error handling isn’t going to help them much because some of the edge conditions are good in some cases and bad in others. In the value-added functions, I intend the debug mode to help power users to get things set up, and then things should be humming and they should turn it off.

But what do we tell the user if there’s a problem? “I couldn’t write that item. Please try again”? Remember that the SOAP Web Services are *extremely* reliable. I can’t even recall an instance where I’ve seen a call to an operation fail when it’s passed good data and the servers are awake. We can assume that calls are going to work.

What do you think about all of this? How would you suggest I improve SPServices error handling?

8 Comments

  1. Marc,

    The first line of code in my completefunc functions is console.log( $( xData.responseXML ) );. That’s all the debugging anyone developing with SPServices core should need (and if you aren’t using it, you are missing out :). It’s very easy to look at the returned XML and see what’s going on this way.

    The value-added functions are great for power users, and the debug messages helped me immensely when I was getting started with SPServices a few years ago (wow, has it been that long?), but I don’t think you can reasonably provide generic error handling for all cases.

    Another check I’ve used in the completefunc for UpdateListItems operations in my SPTools project is:
    var errorCode = $( xData.responseXML ).find( ‘ErrorCode’ ).text();
    if ( errorCode !== “0x00000000” ) {
    // There was an error code in the returned XML
    // My error-handling code goes here
    }

    Reply
  2. Console.log isn’t any use to our XP/IE7 universe, but I’ve discovered I had to add error handling to an application that copies data from a list created by importing an Excel spreadsheet. The copy process was failing on two types of conditions. I only recall the more recent one: a field specified to have a maximum of 255 characters was occasionally being fed more. SharePoint’s response to this is to abort the row copy, continuing with the rest of the rows, and that record (not just the field) does not write. No error is visible.

    This application is only run by administrator types, so displaying errors is just fine.


    completefunc: function(xData, Status) {
    if(Status == ‘success’) {
    var strError = $(xData.responseXML).SPFilterNode(‘ErrorText’).text();
    if(strError != “”) {
    $(“#showErrors”).append(“Error adding: ” + $(xData.responseXML).SPFilterNode(‘z:row’).attr(“ows_Title”) + ” ” + strError + “”);
    }
    } else alert(“error: ” + xData.responseText);
    } //completefunc

    Reply
  3. Hi Marc,

    This is my generic error handler… (it returns a jquery object to save doing $() twice).
    I can’t quite remember why I included all these nodes and options, but it was after a few sessions with Firebug, which I found more usable for this sort of debugging than IE.
    It does pull out useful error messages like “Invalid Date/Time” in list updates, etc, and seems to catch most things so far.

    function spParseAndCheck(xData,Status) {
    var $xml = $(xData.responseXML);
    var spErrorcode = $xml.find(“ErrorCode”).text(); // 0x00000000
    var spErrortext = $xml.find(“ErrorText”).text() + $xml.find(“errorstring”).text();
    if (Status==’success’ && (spErrorcode==” ||spErrorcode==’0x00000000′) && spErrortext==”) return $xml; // Success
    var err = sprintf(‘Error in SPServices call\n SharePoint errorcode={%s}\n ErrorText={%s}\n SPServices status={%s}’,spErrorcode,spErrortext,Status);
    // deal with error here – throw?

    }

    /Mark

    Reply

Have a thought or opinion?