Skip to content

PROD-77638 - Prevent double-stringify of DLQ messages on catch path#75

Open
Dimitris-Ilias wants to merge 1 commit intoWorkable:masterfrom
Dimitris-Ilias:prevent_double_stringify_on_dlq_catch_path
Open

PROD-77638 - Prevent double-stringify of DLQ messages on catch path#75
Dimitris-Ilias wants to merge 1 commit intoWorkable:masterfrom
Dimitris-Ilias:prevent_double_stringify_on_dlq_catch_path

Conversation

@Dimitris-Ilias
Copy link
Copy Markdown
Contributor

@Dimitris-Ilias Dimitris-Ilias commented May 7, 2026

Summary

The BaseQueueHandler.addToDLQ catch-path corrupts message payloads when the primary DLQ publish or afterDlq hook fails, producing double-encoded messages on the DLQ that downstream consumers cannot decode back to their original shape.

Before this PR

When a message fails repeatedly and the primary addToDLQ flow throws (e.g. afterDlq raises during transient broker instability or downstream errors), execution falls into the catch block:

} catch (err) {
  this.logger.error(err);
  await this.rabbit.publish(this.dlqName, msg.content.toString(), msg.properties);
  ack(err.message, null);
}
  • msg.content is the original raw Buffer of already-encoded JSON; calling .toString() yields a JSON string. rabbit.publish then routes it through encode() which calls JSON.stringify again, producing a double-encoded payload. For an original event of {"foo":1}, the DLQ ends up with "{\"foo\":1}"
  • Any consumer that decodes this twin gets a plain string instead of the expected object — handlers and DLQ replay tooling break

After this PR

  • Catch-path passes msg.content (the raw Buffer) directly to rabbit.publish instead of msg.content.toString(). The DLQ entry is now byte-identical to the original message.
  • encode() short-circuits on Buffer.isBuffer(message) and returns the Buffer unchanged. This honors the type contract and is what allows the catch-path to keep using the high-level rabbit.publish API without dropping to channel.sendToQueue.
  • Catch-path error log now includes the correlationId and target DLQ name, matching the [correlationId]-prefixed convention used elsewhere in the file.
  • Test rewritten to subscribe to the DLQ and assert that delivered messages decode round-trip to the original event object, catching regressions at the actual broker boundary instead of the publish argument.

Follow-ups

The catch-path may still publish two messages to the DLQ when afterDlq throws after a successful first publish (one from the try-block, one from the catch). This PR fixes the malformation but not the duplication. The new test already exercises that path and can be extended in a follow-up PR to assert deduplicated behavior.

@Dimitris-Ilias Dimitris-Ilias changed the title Prevent double-stringify of DLQ messages on catch path PROD-77638 - Prevent double-stringify of DLQ messages on catch path May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant