Skip to content

fix: preserve $ characters in interpolated error message values#34220

Open
anxkhn wants to merge 2 commits into
cypress-io:developfrom
anxkhn:patch-11
Open

fix: preserve $ characters in interpolated error message values#34220
anxkhn wants to merge 2 commits into
cypress-io:developfrom
anxkhn:patch-11

Conversation

@anxkhn

@anxkhn anxkhn commented Jul 4, 2026

Copy link
Copy Markdown
Contributor
  • Closes

Additional details

stripIndent() (packages/errors/src/stripIndent.ts) is the substitution engine behind the errTemplate tagged-template system that formats Cypress error messages. errTemplate calls stripIndent(templateStrings, ...templateArgs) and stripIndent splices each interpolated value into a <<i>> placeholder with:

result = result.replace(`<<${i}>>`, `${arg}`)

String.prototype.replace with a string replacement interprets $ sequences in that replacement. Since the search argument here is a literal placeholder (no capture groups), the sequences that apply are $& (the matched placeholder), $` (text before the match), $' (text after the match), and $$ (an escaped $). So any interpolated value containing one of those was corrupted in the rendered error. For example, an error that embeds JSON-stringified data:

  • value: {"expr":"a$&b"}
  • rendered (before): ... {"expr":"a<<0>>b"} (the raw <<0>> placeholder leaks back in via $&)
  • rendered (after): ... {"expr":"a$&b"}

The fix passes a replacer function instead of a string. A function's return value is inserted literally and is not subject to $-pattern interpretation, so values are rendered verbatim. This is a one-line change with no behavior change for any value that does not contain those $ sequences; the package's 160 error-render snapshot tests are unaffected.

This is a self-identified correctness fix with no linked issue. Per CONTRIBUTING.md, purely mechanical/correctness fixes may be submitted without a prior issue as long as the reasoning is explained here. Happy to open a tracking issue first if the maintainers prefer.


Note

Low Risk
One-line behavioral fix in internal error templating with a targeted unit test; no public API or runtime test-path changes beyond clearer error messages.

Overview
Fixes garbled Cypress error text when errTemplate / stripIndent splice interpolated values that contain JavaScript replacement patterns ($&, $`, $', $$).

stripIndent now passes a replacer function to String.prototype.replace instead of a string replacement, so interpolated args (for example JSON in config validation errors) render verbatim. A unit test covers the regression, and 15.18.1 changelog documents the user-facing fix.

Reviewed by Cursor Bugbot for commit 25e3109. Bugbot is set up for automated code reviews on this repo. Configure here.

Steps to test

A new unit test in packages/errors/test/stripIndent.spec.ts covers this. To reproduce manually:

  1. yarn workspace @packages/errors test -- test/stripIndent.spec.ts
  2. The added case interpolates a value containing $&, $`, $' and $$ and asserts it renders verbatim. On the previous code it renders the corrupted string (e.g. leaking <<0>> and re-inserting surrounding text); with this change it renders the value unchanged.

The full package suite (yarn workspace @packages/errors test, 184 tests including the 160 visualSnapshotErrors renders) and yarn workspace @packages/errors check-ts both pass.

How has the user experience changed?

Cypress error messages that interpolate a value containing $&, $`, $' or $$ (for example JSON-stringified data shown in a config-validation error) are now rendered exactly as-is instead of being garbled by JavaScript's replacement-pattern handling. There is no visual change for messages whose interpolated values do not contain those sequences.

PR Tasks

  • [na] Is there an associated issue with maintainer approval for PR submission?
  • Have tests been added/updated?
  • [na] Has a PR for user-facing changes been opened in cypress-documentation?
  • [na] Have API changes been updated in the type definitions?

@cypress-app-bot

Copy link
Copy Markdown
Collaborator

@jennifer-shehane

Copy link
Copy Markdown
Member

@anxkhn Please add a changelog entry

anxkhn added 2 commits July 7, 2026 22:07
stripIndent() substitutes each interpolated value into its errTemplate placeholder with String.prototype.replace and a string replacement. Because the search argument is a literal placeholder (no capture groups), a value containing `$&`, `$\``, `$'` or `$$` was interpreted as a special replacement pattern and corrupted the rendered message. Such values are common, for example JSON-stringified data embedded in an error.

Pass a replacer function so the value is inserted literally.
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.

3 participants