1

I am trying to understand why the following is happening:

<script runat="server">
    try{
        Platform.Response.Redirect('http://www.google.com');
    } catch(e) {
        Platform.Response.Redirect('http://www.yahoo.com');
    }
</script>

This code triggers the catch redirect. Why does it trigger the redirect of the catch block instead of the redirect in the try block. If I redirect from the catch block to a handler page and pass "e" I can see the following error:

{"message":"Error in the application.","description":"ExactTarget.OMM.AMPScriptRedirectException: Error in the application. - from Jint\r\n\r\n"}

If I remove or comment out the catch redirect, the redirect to google.com works fine. If I change the try block to anything but a redirect, it also works as expected. It seems only happen when there is a redirect in the try and catch block.

The above is the entire code.

Any ideas anyone?

Edit: There is another post regarding the same issue from earlier this year but with no response: https://stackoverflow.com/questions/60343379/ssjs-platform-response-redirect-throws-error-in-try-catch-statement

4

So, this is a known issue in .Net (which is what is used for rendering SFMC SSJS). Using Redirect will throw a Thread Abort Exception. Which I believe is what @SamWhitmore was stating in the official SFMC statement he provided. And as we do not have the control on catching exceptions that you do with .Net, we have to think outside the box.

The best way to get around this that I have found is to place a conditional in your catch statement. By putting the condition in, you can have it where the redirect does not appear in the catch if the error is "ExactTarget.OMM.AMPScriptRedirectException: Error in the application. - from OMMCommon\r\n\r\n" so then the try will run successfully as the redirect will no longer exist in the catch to cause the above stated issues.

Something like:

<script runat="server">
    var redirect = 'https://google.com'

    try{
          Platform.Response.Redirect(redirect + '?s=pass')
    } catch(e) {
        var desc = e.description; //Pulls the description from error object
        if(desc.indexOf("ExactTarget.OMM.AMPScriptRedirectException") > -1) {
          Platform.Response.Write(desc) //This is arbitrary as will not be run
        } else {
          redirect = 'https://yahoo.com'
          Platform.Response.Redirect(redirect)
        }
    }
</script>

For testing I had both go to google with the try adding the parameter of s=pass and failure (catch) pulling in the parameter of e that contains the error description. This way if there was an error, like writing Plaatform instead of Platform it would redirect with the error description inside the parameter or e, but if all was right in the try part, it would hide the redirect inside the conditional, allowing the try to run correctly.

Edited to include indexOf instead of direct string match and to change redirect in catch to a different URL to remove any confusion on including error description inside of query parameter of redirect URL.

| improve this answer | |
  • Thanks Gortonington. Your example is great but I believe you would need to stringify the desc in the catch redirect as otherwise this will cause an error. Also, I would set redirect 2nd parameter to false so it becomes a 302 rather a permanent 301. Last but not least you get 'OMMCommon' while I get 'Jint'. I have changed it to a include() – shd.lux Jul 10 at 14:02
  • desc is set to pull the description from the e object, so it will return the string value associated with the description property. There should be no need to Stringify it. And setting to false is an option if you want, but not necessary. I have successfully used and tested the above in my instance without error. – Gortonington Jul 10 at 14:28
  • and as to the JInt part. You can just change it to look at the indexOf the important part, like if(desc.indexOf('ExactTarget.OMM.AMPScriptRedirectException') > -1) { – Gortonington Jul 10 at 14:33
  • I disagree with you here. 1: Without Stringify you will get: {"message":"Redirect URI cannot contain newline characters.","description":"System.ArgumentException: Redirect URI cannot contain newline characters. - from Jint\r\n\r\n"}. – shd.lux Jul 11 at 22:02
  • 2: If you set the second param true, in some browsers, testing becomes harder as the redirect is a 301 and without clearing the browser cache the redirect can be hard set inside the browser not allowing you to test anymore the page itself. Also, I believe there are only a very few cases where a 301 on a CloudPage would make sense as the Redirect is used to move from one page to another rather telling the browser the resource is not there anymore – shd.lux Jul 11 at 22:06
2

I talked with one of the developers of SSJS and he told me:

Redirect works by throwing an exception, so if it is inside a try it will indeed always end up in the catch statement. The one in the catch will overwrite the location set by the first one, and generate a new exception. It is similar to the ThreadAbort exceptions generated when calling the default Response.Redirect method in .net.

So, it's functioning as designed, which doesn't necessarily help you out if you've got a redirect buried in a function or other code that then gets called inside a try block. But it's at least an answer.

| improve this answer | |
1

Refer to the SSJS Redirect function syntax.

Try the below code -

<script runat="server" language="javascript">
Platform.Load("core", "1.1.1");     // Load core library

try {
    Redirect("http://www.google.com",true); 
 } 
 catch(e) {
    Redirect("http://www.yahoo.com",true);
} 
 </script>
| improve this answer | |
  • Same issue - I have tried it with lib 1.1.1 to 1.1.5, loading Platform or reference Platform, tried with true, false or null. The result is the same. Is this code working for you? It does not for me – shd.lux Jul 6 at 21:46
  • Platform.Response.Redirect() and Redirect() are the same functions. Platform.Response.Redirect is faster, though, as you don't have to load the entire core library to use it. It's a best practice to avoid the core functions (Platform.Load) as much as possible. – Sam Whitmore Jul 7 at 18:38
  • As a note @SamWhitmore they are technically two different functions that translate to the same exact action. (I know, semantics and all that jazz... :X) As to the speed, it is the library call that adds the time, not the function. BUT loading the Core Library is not as huge of a draw as many perceive it to be too. I would not say you should avoid Core at all costs in any way. It is more consider what library/language best suits your needs. There are many places (especially in Landing pages) that utilizing Core actually helps you speed up and make your code more efficient/elegant. – Gortonington Jul 12 at 11:17
1

I do not really know why - but I know how to restructure the code that it will work:

<script runat="server">
    var redirect = 'http://www.google.com'
  
    try{
        //do your stuff here
    } catch(e) {
        redirect = 'http://www.yahoo.com'
    }
  
    Platform.Response.Redirect(redirect)
</script>
| improve this answer | |
  • Thanks Daniel - this indeed works as the redirect is outside the try block. It seems that Redirect always throws an error and triggers whatever is in the catch block. Why Redirect throws an error is a mystery :-) – shd.lux Jul 7 at 7:35
0

The answer from Daniel Koch works pretty well and I can see no logical explanation why this is happen but the Redirect always throws an error. Instead of re-writing your code, I come up with this solution based of Daniel's answer:

<script runat="server" language="javascript">
Platform.Load("core", "1.1.1");

try {

    // do stuff
    try{
        Redirect("http://www.google.com", false);    
    } catch(e) {}

} catch (e) {
    Redirect("http://www.yahoo.com", false);
}
</script>
| improve this answer | |
  • I would be wary of nesting try/catch statements in this way. It works for this simple instance for sure, but anything that starts to get more complex it can cause issues as anything declared in a try or catch block is considered a local variable and will not transfer outside of that block without expressly being returned. Plus, it is far from efficient processing. – Gortonington Jul 8 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.