This is more like a pre-Velocity tip, since you need to make this decision while setting up your Marketo and/or SFDC Custom Objects, before you even try to read them using Velocity.

Don't start your Custom Object names with numbers, as they cannot be used from Velocity.

Neither SFDC nor Marketo will stop you from creating such COs, and Marketo will even show them in the script editor:

But your Velocity scripts will always error out if you use those objects (with the unhelpful error message String index out of range -1).

The reason?

In Velocity, Custom Objects are accessed as $references, which are Java objects (ArrayLists, to be exact) under the hood. Ignoring the leading $, they're are subject to Java's variable naming conventions:

A variable's name can be any legal identifier — an unlimited-length sequence of Unicode letters and digits, beginning with a letter, the dollar sign "$", or the underscore character "_". Subsequent characters may be letters, digits, dollar signs, or underscore characters. I probably just confused you, but had no choice. This passage from the Java docs is talking about the Java level allowing names that start with a $ followed by a digit, i.e. wholly within Java you're allowed to use a name like $2018Purchases__cList. But Velocity adds its own $ on top of the real Java name. So the real Java name is simply 2018Purchases__cList, ergo a name starting with a digit, ergo illegal in Java.

Generally speaking, this is one of those real-world data type limitations that you wouldn't know about if you only read the SFDC and Marketo docs, which both allow CO names to be “numeroalphabetic” strings.