{"record":{"id":"1ca8238397a0e1c6","repo":"flowable/flowable-engine","slug":"unterminated-string","errorCode":null,"errorMessage":"unterminated string","messagePattern":"unterminated string","errorType":"exception","errorClass":"ScanException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/Scanner.java","lineNumber":311,"sourceCode":"\t\tif (escaped) {\n\t\t\tbuilder.append('\\\\');\n\t\t}\n\t\treturn token(Symbol.TEXT, builder.toString(), i - position);\n\t}\n\t\n\t/**\n\t * string token\n\t */\n\tprotected Token nextString() throws ScanException {\n\t\tbuilder.setLength(0);\n\t\tchar quote = input.charAt(position);\n\t\tint i = position+1;\n\t\tint l = input.length();\n\t\twhile (i < l) {\n\t\t\tchar c = input.charAt(i++);\n\t\t\tif (c == '\\\\') {\n\t\t\t\tif (i == l) {\n\t\t\t\t\tthrow new ScanException(position, \"unterminated string\", quote + \" or \\\\\");\n\t\t\t\t} else {\n\t\t\t\t\tc = input.charAt(i++);\n\t\t\t\t\tif (c == '\\\\' || c == '\\'' || c == '\\\"') {\n\t\t\t\t\t\tbuilder.append(c);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new ScanException(position, \"invalid escape sequence \\\\\" + c, \"\\\\', \\\\\\\" or \\\\\\\\\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (c == quote) {\n\t\t\t\treturn token(Symbol.STRING, builder.toString(), i - position);\n\t\t\t} else {\n\t\t\t\tbuilder.append(c);\n\t\t\t}\n\t\t}\n\t\tthrow new ScanException(position, \"unterminated string\", String.valueOf(quote));\n\t}\n\t\n\t/**","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/Scanner.java#L293-L329","documentation":"Scanner.nextString() throws ScanException('unterminated string') when a string literal ends with a lone backslash: the input ends immediately after an escape character, so the closing quote is never reached. The 'expected' field indicates the closing quote or another escape character was needed.","triggerScenarios":"An EL string literal where the input terminates right after a backslash, e.g. \"${'abc\\\\'\" (backslash is the last character of the input), encountered while scanning inside a quoted string.","commonSituations":"Expressions generated by templates or shell scripts where trailing backslashes escape quotes incorrectly; Windows-style paths written as '${'C:\\\\users\\\\' }' with an odd number of backslashes; manual edits that dropped the closing quote.","solutions":["Ensure the string literal has a closing quote and does not end with a dangling backslash.","Double the backslash ('\\\\') when a literal backslash is intended before the end of the string.","Log the ScanException position to find the exact spot in the expression."],"exampleFix":"// before\nString expr = \"${'C:\\\\path\\\\'\"; // ends with lone backslash\n// after\nString expr = \"${'C:\\\\path\\\\user'}\";","handlingStrategy":"validation","validationCode":"boolean endsWithDanglingBackslash(String expr) { return expr.endsWith(\"\\\\\"); }\n// reject before building","typeGuard":null,"tryCatchPattern":"try {\n    builder.build(expr);\n} catch (TreeBuilderException e) {\n    if (\"unterminated string\".equals(e.getMessage())) {\n        throw new IllegalArgumentException(\"Dangling backslash or missing quote in: \" + expr);\n    }\n    throw e;\n}","preventionTips":["Never end a string literal with a single backslash; double it for a literal backslash.","Use forward slashes or File/Path APIs for paths instead of backslash literals.","Escape via the source language's rules before the string reaches EL.","Lint expressions for trailing backslashes in config."],"tags":["el","scanner","string-literal","escape-sequence"],"backgroundTag":"invalid-argument-format","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}