diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 54bf4d1d6b7..0113eb4e3d1 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -818,96 +818,94 @@ fn find_skips_from_snippet(
         _ => return (vec![], false),
     };
 
-    fn find_skips(snippet: &str, is_raw: bool) -> Vec<usize> {
-        let mut s = snippet.char_indices();
-        let mut skips = vec![];
-        while let Some((pos, c)) = s.next() {
-            match (c, s.clone().next()) {
-                // skip whitespace and empty lines ending in '\\'
-                ('\\', Some((next_pos, '\n'))) if !is_raw => {
-                    skips.push(pos);
-                    skips.push(next_pos);
-                    let _ = s.next();
-
-                    while let Some((pos, c)) = s.clone().next() {
-                        if matches!(c, ' ' | '\n' | '\t') {
-                            skips.push(pos);
-                            let _ = s.next();
-                        } else {
-                            break;
-                        }
-                    }
-                }
-                ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => {
-                    skips.push(next_pos);
-                    let _ = s.next();
-                }
-                ('\\', Some((_, 'x'))) if !is_raw => {
-                    for _ in 0..3 {
-                        // consume `\xAB` literal
-                        if let Some((pos, _)) = s.next() {
-                            skips.push(pos);
-                        } else {
-                            break;
-                        }
-                    }
-                }
-                ('\\', Some((_, 'u'))) if !is_raw => {
-                    if let Some((pos, _)) = s.next() {
-                        skips.push(pos);
-                    }
-                    if let Some((next_pos, next_c)) = s.next() {
-                        if next_c == '{' {
-                            // consume up to 6 hexanumeric chars
-                            let digits_len =
-                                s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).count();
-
-                            let len_utf8 = s
-                                .as_str()
-                                .get(..digits_len)
-                                .and_then(|digits| u32::from_str_radix(digits, 16).ok())
-                                .and_then(char::from_u32)
-                                .map_or(1, char::len_utf8);
-
-                            // Skip the digits, for chars that encode to more than 1 utf-8 byte
-                            // exclude as many digits as it is greater than 1 byte
-                            //
-                            // So for a 3 byte character, exclude 2 digits
-                            let required_skips =
-                                digits_len.saturating_sub(len_utf8.saturating_sub(1));
-
-                            // skip '{' and '}' also
-                            for pos in (next_pos..).take(required_skips + 2) {
-                                skips.push(pos)
-                            }
-
-                            s.nth(digits_len);
-                        } else if next_c.is_digit(16) {
-                            skips.push(next_pos);
-                            // We suggest adding `{` and `}` when appropriate, accept it here as if
-                            // it were correct
-                            let mut i = 0; // consume up to 6 hexanumeric chars
-                            while let (Some((next_pos, c)), _) = (s.next(), i < 6) {
-                                if c.is_digit(16) {
-                                    skips.push(next_pos);
-                                } else {
-                                    break;
-                                }
-                                i += 1;
-                            }
-                        }
-                    }
-                }
-                _ => {}
-            }
-        }
-        skips
+    if str_style.is_some() {
+        return (vec![], true);
     }
 
-    let r_start = str_style.map_or(0, |r| r + 1);
-    let r_end = str_style.unwrap_or(0);
-    let s = &snippet[r_start + 1..snippet.len() - r_end - 1];
-    (find_skips(s, str_style.is_some()), true)
+    let snippet = &snippet[1..snippet.len() - 1];
+
+    let mut s = snippet.char_indices();
+    let mut skips = vec![];
+    while let Some((pos, c)) = s.next() {
+        match (c, s.clone().next()) {
+            // skip whitespace and empty lines ending in '\\'
+            ('\\', Some((next_pos, '\n'))) => {
+                skips.push(pos);
+                skips.push(next_pos);
+                let _ = s.next();
+
+                while let Some((pos, c)) = s.clone().next() {
+                    if matches!(c, ' ' | '\n' | '\t') {
+                        skips.push(pos);
+                        let _ = s.next();
+                    } else {
+                        break;
+                    }
+                }
+            }
+            ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => {
+                skips.push(next_pos);
+                let _ = s.next();
+            }
+            ('\\', Some((_, 'x'))) => {
+                for _ in 0..3 {
+                    // consume `\xAB` literal
+                    if let Some((pos, _)) = s.next() {
+                        skips.push(pos);
+                    } else {
+                        break;
+                    }
+                }
+            }
+            ('\\', Some((_, 'u'))) => {
+                if let Some((pos, _)) = s.next() {
+                    skips.push(pos);
+                }
+                if let Some((next_pos, next_c)) = s.next() {
+                    if next_c == '{' {
+                        // consume up to 6 hexanumeric chars
+                        let digits_len =
+                            s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).count();
+
+                        let len_utf8 = s
+                            .as_str()
+                            .get(..digits_len)
+                            .and_then(|digits| u32::from_str_radix(digits, 16).ok())
+                            .and_then(char::from_u32)
+                            .map_or(1, char::len_utf8);
+
+                        // Skip the digits, for chars that encode to more than 1 utf-8 byte
+                        // exclude as many digits as it is greater than 1 byte
+                        //
+                        // So for a 3 byte character, exclude 2 digits
+                        let required_skips = digits_len.saturating_sub(len_utf8.saturating_sub(1));
+
+                        // skip '{' and '}' also
+                        for pos in (next_pos..).take(required_skips + 2) {
+                            skips.push(pos)
+                        }
+
+                        s.nth(digits_len);
+                    } else if next_c.is_digit(16) {
+                        skips.push(next_pos);
+                        // We suggest adding `{` and `}` when appropriate, accept it here as if
+                        // it were correct
+                        let mut i = 0; // consume up to 6 hexanumeric chars
+                        while let (Some((next_pos, c)), _) = (s.next(), i < 6) {
+                            if c.is_digit(16) {
+                                skips.push(next_pos);
+                            } else {
+                                break;
+                            }
+                            i += 1;
+                        }
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+    (skips, true)
 }
 
 #[cfg(test)]
diff --git a/src/test/ui/fmt/format-raw-string-error.rs b/src/test/ui/fmt/format-raw-string-error.rs
new file mode 100644
index 00000000000..9f0bc01a749
--- /dev/null
+++ b/src/test/ui/fmt/format-raw-string-error.rs
@@ -0,0 +1,3 @@
+fn main() {
+    println!(r#"\'\'\'\'\'\'\'\'\'\'\'\'\'\'}"#); //~ ERROR invalid format string: unmatched `}` found
+}
diff --git a/src/test/ui/fmt/format-raw-string-error.stderr b/src/test/ui/fmt/format-raw-string-error.stderr
new file mode 100644
index 00000000000..8d61950d8c2
--- /dev/null
+++ b/src/test/ui/fmt/format-raw-string-error.stderr
@@ -0,0 +1,10 @@
+error: invalid format string: unmatched `}` found
+  --> $DIR/format-raw-string-error.rs:2:45
+   |
+LL |     println!(r#"\'\'\'\'\'\'\'\'\'\'\'\'\'\'}"#);
+   |                                             ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/fmt/issue-104142.rs b/src/test/ui/fmt/issue-104142.rs
new file mode 100644
index 00000000000..8d7283a7197
--- /dev/null
+++ b/src/test/ui/fmt/issue-104142.rs
@@ -0,0 +1,6 @@
+fn main() {
+    println!(
+        r#"
+    \"\'}、"# //~ ERROR invalid format string: unmatched `}` found
+    );
+}
diff --git a/src/test/ui/fmt/issue-104142.stderr b/src/test/ui/fmt/issue-104142.stderr
new file mode 100644
index 00000000000..d41644faa28
--- /dev/null
+++ b/src/test/ui/fmt/issue-104142.stderr
@@ -0,0 +1,10 @@
+error: invalid format string: unmatched `}` found
+  --> $DIR/issue-104142.rs:4:9
+   |
+LL |     \"\'}、"#
+   |         ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: aborting due to previous error
+