Blog |

How to Handle the Unclosed String Literal Error in Java

How to Handle the Unclosed String Literal Error in Java
Table of Contents

Introduction to Strings & String Literals

Strings are a fundamental data type in most modern general-purpose programming languages. In Java, strings are defined as character sequences and are represented as immutable objects of the class java.lang.String which contains various constructors and methods for creating and manipulating strings [1]. A string literal is simply a reference to an instance of the String class, which consists of zero or more characters enclosed in double quotes. Moreover, a string literal is also a constant, which means it always refers to the same instance of the String class, due to interning [2]. Below is an example of the string literal "rollbar" being assigned to two different variables a and b which both reference the same (automatically interned) String object.

String a = "rollbar";
String b = "rollbar";
System.out.println(a == b); // true

For string literals to be interpreted correctly by the Java compiler, certain (so called “special”) characters need to be escaped by using the appropriate escape sequence (or escape for short) [3]. Such is the case with the double quote character, which is considered a special character as it is used to mark the beginning and the end of a string literal. So, in order to have quotes within these quotes, one must use the escape sequence \” on the inner quotes, as shown below.

System.out.println("Say \"Hi!\" to Rollbar."); // Say "Hi!" to Rollbar.

 

Unclosed String Literal Error: What It Is and Why It Happens?

As its name implies, the unclosed string literal error refers to a string literal which has not been closed. More specifically, this means that the Java compiler has failed to interpret a string literal due to being unable to locate the double quote expected to close i.e., mark the end of it. The message generated by the compiler indicates the line and the position where the opening quotation mark of the string literal in question is found.

The unclosed string literal error most commonly occurs when

  • a string literal doesn’t end with a double quote;
  • a string literal extends beyond a single line but is not concatenated properly; or
  • a double quote is part of the string literal itself but is not escaped properly.

 

Unclosed String Literal Error Examples

Missing double quotes at the end of a string literal

When the Java compiler encounters a double quote which denotes the start of a string literal, it expects to find a matching double quote that marks the end of it. In other words, double quotes always go in pairs, and failing to match an opening quote to a closing one will inevitably trigger the unclosed string literal error.

Fig. 1(a) shows how failing to mark the end of a string literal with a double quote results in the unclosed string literal error, and the error message points to the location where the opening quote appears in the code. Adding the omitted quote, as demonstrated in Fig. 1(b), closes the string literal and remedies the issue.

(a)

1
2
3
4
5
6
7
8
package rollbar;

public class UnclosedStringLiteral {

  public static void main(String... args) {
    System.out.println("This is a simple string literal.);
  }
}
UnclosedStringLiteral.java:6: error: unclosed string literal
    System.out.println("This is a simple string literal.);
                       ^
1 error

(b)

1
2
3
4
5
6
7
8
package rollbar;

public class UnclosedStringLiteral {

  public static void main(String... args) {
    System.out.println("This is a simple string literal.");
  }
}
This is a simple string literal.

Figure 1: Unclosed string literal (a) error and (b) resolution

 

Multiline string not concatenated properly

Oftentimes, a string holds textual content too long to be comfortably contained in a single line of code. This raises the need for truncating the string into multiple lines, and the most common way to do this in Java is by splitting the string up into multiple string literals concatenated with the plus (+) character.

Having a single string literal span multiple lines of code is syntactically incorrect, so failing to divide the string into separate, properly concatenated chunks will raise the unclosed string literal error, as can be observed in Fig. 2(a). Note how the compiler flags the second double quote on line 8 as the beginning of a new string literal, rather than the end of the previous one, as it sits on a different line. Encapsulating each sub-string into its own string literal and joining them with the plus character fixes the problem (Fig. 2(b)).


(a)

1
2
3
4
5
6
7
8
9
10
package rollbar;

public class UnclosedStringLiteralMultiline {

  public static void main(String... args) {
    System.out.println("This is a complete sentence
        represented as a multiline string
        in the Java programming language.");
  }
}
UnclosedStringLiteralMultiline.java:6: error: unclosed string literal
    System.out.println("This is a complete sentence
                       ^
UnclosedStringLiteralMultiline.java:7: error: ';' expected
        represented as a multiline string
                      ^
UnclosedStringLiteralMultiline.java:7: error: ';' expected
        represented as a multiline string
                                  ^
UnclosedStringLiteralMultiline.java:8: error: ';' expected
        in the Java programming language.");
          ^
UnclosedStringLiteralMultiline.java:8: error: ';' expected
        in the Java programming language.");
                   ^
UnclosedStringLiteralMultiline.java:8: error: ';' expected
        in the Java programming language.");
                                        ^
UnclosedStringLiteralMultiline.java:8: error: unclosed string literal
        in the Java programming language.");
                                         ^
7 errors

(b)

1
2
3
4
5
6
7
8
9
10
package rollbar;

public class UnclosedStringLiteralMultiline {

  public static void main(String... args) {
    System.out.println("This is a complete sentence " +
        "represented as a multiline string " +
        "in the Java programming language.");
  }
}
This is a complete sentence represented as a multiline string in the Java programming language.

Figure 2: Unclosed string literal in multiline string (a) error and (b) resolution

 

Unescaped double quotes inside string literal

As mentioned earlier, certain characters inside string literals need to be escaped in order to be interpreted correctly by the Java compiler. In the case of the double quote ("), it has to be escaped with a preceding backslash (\) so that it doesn’t get misinterpreted as the character marking the end of the string. Fig. 3 shows an example of a string literal containing the double quote character as its second-last character, and how failing to escape it with a backslash invokes the unclosed string literal error.

(a)

1
2
3
4
5
6
7
8
9
package rollbar;

public class UnclosedStringLiteralEscapeSequence {

  public static void main(String... args) {
    String text = "You have to escape ".";
    System.out.println(text);
 }
}
UnclosedStringLiteralEscapeSequence.java:6: error: unclosed string literal
    String text = "You have to escape ".";
                                        ^
UnclosedStringLiteralEscapeSequence.java:6: error: ';' expected
    String text = "You have to escape ".";
                                          ^
2 errors

(b)

1
2
3
4
5
6
7
8
9
package rollbar;

public class UnclosedStringLiteralEscapeSequence {

  public static void main(String... args) {
    String text = "You have to escape \".";
    System.out.println(text);
  }
}
You have to escape ".

Figure 3: Unclosed string literal with unescaped double quote (a) error and (b) resolution

 

Text Blocks to the Rescue

Many of the issues leading to the unclosed string literal error can be prevented by using text blocks, a relatively new feature added to the Java language specification [4]. A text block is a multi-line string literal that avoids the need for most escape sequences, automatically formats the string in a predictable way, and gives good control over the desired output. Text blocks were proposed in 2019 and became a preview feature in JDK 13 & 14, finally making their appearance as a permanent feature in JDK 15, in 2020 [5].

In Java, embedding a snippet of HTML, XML, SQL, or JSON in a string literal can be especially daunting as it tends to require significant editing with escapes and concatenation before the code can compile. Fig. 4(a) shows how such a snippet can be difficult to read and maintain, and how easily it could trigger the unclosed string literal error. Contrast this to the example in Fig. 4(b) which uses a text block to produce the same exact result.

(a)

1
2
3
4
5
6
7
8
9
10
11
12
package rollbar;

public class TextBlocks {
    public static void main(String... args) {
        String html = "<html>\n" +
                  "    <body>\n" +
                  "        <p>\"Hello world\"</p>\n" +
                  "    </body>\n" +
                  "</html>\n";
        System.out.println(html);
    }
}
<html>
    <body>
        <p>"Hello world"</p>
    </body>
</html>

(b)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package rollbar;

public class TextBlocks {

    public static void main(String... args) {
        String html = """
                      <html>
                          <body>
                              <p>"Hello world"</p>
                          </body>
                      </html>
                      """;
        System.out.println(html);
    }
}
<html>
    <body>
        <p>"Hello world"</p>
    </body>
</html>

Figure 4: A multiline HTML string as a (a) chain of string literals versus a (b) text block

It’s apparent how text blocks can improve the readability and writability of Java programs by providing a linguistic mechanism for denoting strings more precisely and elegantly, across multiple lines and without the visual clutter of escape sequences. Still, while some parts of a program may benefit from text blocks laid out over multiple lines, the embedded newline characters and whitespace padding may be undesirable in other parts of the program. Hence, both string literals and text blocks have their own use cases.

 

Conclusion

Strings are a widely used and hugely important device in writing Java programs. Being familiar with the relevant syntax rules is essential in avoiding related compilation errors, such as the unclosed string literal error. This error emerges when the compiler is unable to interpret a string because it can’t figure out where the associated string literal ends. This article helps understand and resolve this error by fixing the underlying syntax issues which provoke it. An alternative way to mitigate and prevent the unclosed string literal error is also proposed, by way of using a new JDK feature—text blocks—as a direct replacement for string literals in certain scenarios.

 

Track, Analyze and Manage Errors With Rollbar

Managing Java errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!

 

References

[1] Oracle, 2020. String (Java SE 15 & JDK 15). Oracle and/or its affiliates. [Online]. Available: https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/String.html. [Accessed Dec. 16, 2021]

[2] Wikipedia, 2021. String interning - Wikipedia. Wikipedia. [Online]. Available: https://en.wikipedia.org/wiki/String_interning. [Accessed Dec. 16, 2021]

[3] Oracle, 2020. The Java® Language Specification. Java SE 15 Edition. Chapter 3. Lexical Structure. Oracle and/or its affiliates. [Online]. Available: https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10.7. [Accessed Dec. 16, 2021]

[4] J. Laskey and S. Marks, 2020. Programmer's Guide to Text Blocks, Oracle and/or its affiliates. [Online]. Available: https://docs.oracle.com/en/java/javase/15/text-blocks/index.html. [Accessed Dec. 16, 2021]

[5] OpenJDK, 2020. JEP 378: Text Blocks. Oracle Corporation and/or its affiliates. [Online]. Available: https://openjdk.java.net/jeps/378. [Accessed Dec. 16, 2021]

Related Posts

See all posts

"Rollbar allows us to go from alerting to impact analysis and resolution in a matter of minutes. Without it we would be flying blind."

Start continuously improving your code today.

Get Started Shape