In my opinion the best solution is to handle these errors in your application and reject them when app has decided that it can't process the message.
If you don't want to lose information, the app should reject the message only after it sent the same message to an error queue.
code is not tested:
q.subscribe({ack: true}, function () {
var numOfRetries = 0;
var args = arguments;
var self = this;
var promise = doWork.apply(self, args);
for (var numOfRetries = 0; numOfRetries < MAX_RETRIES; numOfRetries++) {
promise = promise.fail(function () { return doWork.apply(self, args); });
}
promise.fail(function () {
sendMessageToErrorQueue.apply(self, args);
rejectMessage.apply(self, args);
})
})