Two consecutive hyphens in an XML comment

Guide · Updated July 2026 · ~6 min read

Depending on your tooling you will see this as “The string '--' is not permitted within comments”, “The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment”, or simply “malformed comment”. All three mean the same thing, and the rule behind them surprises almost everyone the first time.

The rule

Inside an XML comment, the two-character sequence -- is forbidden anywhere. Not just at the end — anywhere at all:

<!-- ✗ Invalid: contains "--" in the middle -->
<!-- separator ---------------- -->

<!-- ✗ Invalid: ends with a hyphen, making three in a row -->
<!-- note- -->

<!-- ✓ Valid -->
<!-- separator ================ -->

This is not a parser quirk; it is in the XML specification itself, inherited from SGML. The reason is that --> terminates a comment, and permitting --inside would make finding the true end ambiguous without lookahead. The specification takes the strict route and bans the pair outright.

Where it actually comes from

Commenting out a block that already contains a comment

The single most common cause, and the most confusing, because the code was valid a moment ago. XML comments do not nest:

<!-- disabling this for now
  <server>
    <!-- production only -->
    <port>8080</port>
  </server>
-->

The parser ends the outer comment at the first --> it meets — the one after “production only”. Everything after that becomes live markup again, and the trailing --> is a syntax error. Delete or rename the inner comment before wrapping the block.

ASCII-art dividers

A line of dashes used as a visual separator is instantly invalid. Use equals signs, tildes, or box characters instead. This is why you rarely see dashed rules in hand-maintained XML configuration files.

Commented-out SQL

In MyBatis mappers, Liquibase changelogs, and similar files, people comment out SQL — and SQL's own line-comment marker is --. Two syntaxes collide in one file:

<!-- ✗ Invalid: SQL comment inside an XML comment
  SELECT * FROM users -- only active ones
-->

Text content that happens to contain a double dash

Command-line flags (--verbose), diff output, and prose using an em dash typed as two hyphens all trigger it when they land inside a comment.

How to fix it

Break up the pair

The simplest fix, and it preserves readability. Insert a space between the hyphens, or use a different character entirely:

<!-- ✗ --run-tests -->
<!-- ✓ - -run-tests -->
<!-- ✓ “--run-tests” written with an en dash: –run-tests -->

Do not try to escape it

A natural instinct that does not work: entity references such as &#45; arenot expanded inside comments. The parser sees the characters you literally typed. CDATA does not help either — it governs text content, not comments.

Move the content out of the comment

If the text genuinely needs those characters — a stored SQL snippet, a documented command line — it does not belong in a comment. Put it in an element, where -- is perfectly legal, and wrap it in CDATA if it also contains < or&:

<note><![CDATA[Run with --verbose --dry-run]]></note>

Inside <![CDATA[ … ]]> every character is taken literally, so double hyphens, angle brackets, and ampersands are all safe. OurXML escaping guide covers when CDATA is the right tool and when plain entities are simpler.

To disable a block, delete it — do not comment it

Commenting out large sections of XML is fragile precisely because of the nesting problem. Version control already remembers the old configuration. If you must keep it in the file, rename the element rather than commenting it:

<!-- ✓ Ignored by the application, still valid XML -->
<disabled-server>
  <port>8080</port>
</disabled-server>

Why the message mentions “XML 1.0”

The wording “not mappable to XML 1.0” comes from tools that build a document in memory and then serialise it — Java's DOM/LSSerializer and several XSLT processors phrase it this way. The comment node holds a string that is legal in the object model but cannot be written out as valid XML 1.0 text. In other words the failure appears atserialisation time, so the offending comment may have been introduced programmatically rather than typed by hand. If a template or string concatenation builds your comments, check what it interpolates.

Checklist

  1. Search your file for -- and inspect every hit inside a comment.
  2. Look for a comment nested inside another comment — the usual culprit.
  3. Replace dashed separator lines with equals signs.
  4. Make sure no comment ends with a hyphen right before -->.
  5. Content that truly needs double hyphens belongs in an element with CDATA, not a comment.
  6. Confirm the fix in the XML validator — it reports the exact line.

Frequently asked questions

Can I escape the hyphens with &amp;#45; instead?

No. Entity references are not expanded inside comments — the parser sees the literal text you typed. Character references do not help here.

Does a CDATA section solve it?

No. CDATA changes how text content is parsed, not comments. A comment is a comment all the way to its terminator.

Why can I not nest XML comments?

Because the parser ends a comment at the first "-->" it sees, with no awareness of nesting. The inner comment’s terminator closes the outer one, and the remaining text becomes invalid markup.

Is a single trailing hyphen allowed?

A comment may not end with a hyphen immediately before the terminator, because that would produce three hyphens in a row. Leave a space: write "- -->" rather than "--->".

Keep reading