Unsupported Syntax
24 ES6+ JavaScript features that cause runtime errors in SFMC SSJS, with safe alternatives for each.
The SFMC SSJS engine does not support ES6+ syntax. Using any of the following features will cause a runtime error (often a blank white page with no diagnostic message).
let and const
// ❌ Not supported
let name = "Jane";
const MAX = 100;
// ✅ Use var
var name = "Jane";
var MAX = 100; // Use UPPER_CASE by convention to signal "constant"
Arrow Functions
// ❌ Not supported
var double = (x) => x * 2;
var greet = name => "Hello, " + name;
var fn = () => { return 42; };
// ✅ Use function expressions
var double = function(x) { return x * 2; };
var greet = function(name) { return "Hello, " + name; };
var fn = function() { return 42; };
Template Literals
// ❌ Not supported
var msg = `Hello, ${name}! You have ${count} messages.`;
var html = `<div class="${cls}">${content}</div>`;
// ✅ Use string concatenation
var msg = "Hello, " + name + "! You have " + count + " messages.";
var html = '<div class="' + cls + '">' + content + '</div>';
Classes
// ❌ Not supported
class Animal {
constructor(name) { this.name = name; }
speak() { return this.name + " speaks"; }
}
// ✅ Use constructor functions
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
return this.name + " speaks";
};
// Or use the module/factory pattern (preferred in SSJS)
function createAnimal(name) {
var animal = { speak: speak };
return animal;
function speak() { return name + " speaks"; }
}
Destructuring
// ❌ Not supported — object destructuring
var { name, email } = subscriber;
var { x: alias } = obj;
// ❌ Not supported — array destructuring
var [first, second] = arr;
// ✅ Access properties directly
var name = subscriber.name;
var email = subscriber.email;
var first = arr[0];
var second = arr[1];
Default Parameters
// ❌ Not supported
function greet(name = "Subscriber") { return "Hello, " + name; }
// ✅ Check inside function body
function greet(name) {
name = name || "Subscriber";
return "Hello, " + name;
}
Spread Syntax
// ❌ Not supported
var combined = [...arr1, ...arr2];
var copy = [...arr];
var merged = { ...obj1, ...obj2 };
// ✅ Use concat for arrays
var combined = arr1.concat(arr2);
// ✅ Manual object merge
function merge(a, b) {
var result = {};
for (var k in a) { if (a.hasOwnProperty(k)) result[k] = a[k]; }
for (var k in b) { if (b.hasOwnProperty(k)) result[k] = b[k]; }
return result;
}
Rest Parameters
// ❌ Not supported
function sum(...numbers) { return numbers.reduce((a, b) => a + b, 0); }
// ✅ Use the arguments object
function sum() {
var total = 0;
for (var i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
for…of
// ❌ Not supported
for (var item of items) { process(item); }
// ✅ Use for loop
for (var i = 0; i < items.length; i++) {
process(items[i]);
}
Async / Await
// ❌ Not supported — SSJS has no Promise/async model
async function fetchData() {
const data = await fetch(url);
return data.json();
}
// ✅ SSJS HTTP calls are synchronous by nature
// Script.Util.HttpRequest.send() blocks until the response arrives
var req = new Script.Util.HttpRequest(url);
req.method = "GET";
var resp = req.send(); // Synchronous — no await needed
var data = Platform.Function.ParseJSON(String(resp.content) + "");
Generators
// ❌ Not supported
function* counter() { let n = 0; while (true) { yield n++; } }
// ✅ Use a closure-based counter
function makeCounter() {
var n = 0;
return function() { return n++; };
}
ES Modules (import/export)
// ❌ Not supported
import { lookup } from './helpers.js';
export function myHelper() { ... }
// ✅ All code must be in script blocks or script activity input
// Use the module factory pattern for organization
function DEHelper(deName) {
return { lookup: lookup };
function lookup(field, filterField, filterValue) {
return Platform.Function.Lookup(deName, field, filterField, filterValue);
}
}
Optional Chaining (?.)
// ❌ Not supported
var city = user?.profile?.address?.city;
// ✅ Manual chained checks
var city = (user && user.profile && user.profile.address)
? user.profile.address.city
: undefined;
// Or use a helper
function safeGet(obj, path) {
var parts = path.split(".");
var current = obj;
for (var i = 0; i < parts.length; i++) {
if (current == null) return undefined;
current = current[parts[i]];
}
return current;
}
var city = safeGet(user, "profile.address.city");
Nullish Coalescing (??)
// ❌ Not supported
var name = user.name ?? "Subscriber";
// ✅ Use || for falsy fallback (note: also catches "", 0, false)
var name = user.name || "Subscriber";
// ✅ Explicit null/undefined check when "" or 0 are valid
var name = (user.name !== null && user.name !== undefined) ? user.name : "Subscriber";
Direct Object Literal Returns
This is an SSJS-specific engine bug (not an ES version issue):
// ❌ May cause a 500 error in SSJS
function getConfig() {
return { timeout: 30, retries: 3 };
}
// ✅ Assign to variable first, then return
function getConfig() {
var config = { timeout: 30, retries: 3 };
return config;
}
new on User-Defined Constructors
Using new with custom (non-native) constructor functions can fail if the function uses the revealing module pattern (returns an object):
// ⚠️ Risky — if MyModule uses "return service" pattern, new will fail
var instance = new MyModule(config);
// ✅ Call as a factory function (no new)
var instance = MyModule(config);
new is safe for: Date, RegExp, Error, Object, Array, WSProxy, Script.Util.HttpRequest.