{"record":{"id":"fbfb28f361023f76","repo":"apple/pkl","slug":"doesnotcontainliteralmatch","errorCode":"doesNotContainLiteralMatch","errorMessage":"doesNotContainLiteralMatch","messagePattern":"doesNotContainLiteralMatch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/stdlib/base/StringNodes.java","lineNumber":354,"sourceCode":"    // inefficient but at least correct\n    protected boolean eval(String self, VmRegex regex) {\n      var matcher = regex.matcher(self);\n      var end = -1;\n      while (matcher.find()) {\n        end = matcher.end();\n      }\n      return end == self.length();\n    }\n  }\n\n  public abstract static class indexOf extends ExternalMethod1Node {\n    @TruffleBoundary\n    @Specialization\n    protected long eval(String self, String pattern) {\n      var charIndex = self.indexOf(pattern);\n      if (charIndex == -1) {\n        CompilerDirectives.transferToInterpreter();\n        throw exceptionBuilder()\n            .evalError(\"doesNotContainLiteralMatch\")\n            .withProgramValue(\"String\", self)\n            .withProgramValue(\"Pattern\", pattern)\n            .build();\n      }\n      return self.codePointCount(0, charIndex);\n    }\n\n    @TruffleBoundary\n    @Specialization\n    protected long eval(String self, VmRegex regex) {\n      var matcher = regex.matcher(self);\n      if (!matcher.find()) {\n        CompilerDirectives.transferToInterpreter();\n        throw exceptionBuilder()\n            .evalError(\"doesNotContainRegexMatch\")\n            .withProgramValue(\"String\", self)\n            .withProgramValue(\"Pattern\", regex)","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/stdlib/base/StringNodes.java#L336-L372","documentation":"String.indexOf(pattern) returns the code-point index of the first occurrence of a literal pattern, and throws doesNotContainLiteralMatch when the string does not contain the pattern at all. Pkl deliberately makes the plain indexOf a total failure on missing matches; indexOfOrNull is the null-returning counterpart.","triggerScenarios":"Calling `\"abc\".indexOf(\"x\")` where the literal substring is absent — including case mismatches (\"Hello\".indexOf(\"hello\")), whitespace/encoding differences, or pattern strings built at runtime from user config.","commonSituations":"Parsing config values or paths assuming a separator exists (e.g. \"key=value\".indexOf(\"=\")); splitting identifiers that may lack a prefix; locale/case differences between producer and consumer of the string.","solutions":["Switch to indexOfOrNull(pattern) and handle null, e.g. `s.indexOfOrNull(sep) ?? 0`.","Check membership first with s.contains(pattern) before calling indexOf.","Normalize case/whitespace (toLowerCase, trim) on both string and pattern when formatting may vary.","If a default position is acceptable, use the null-coalescing pattern rather than relying on the throw."],"exampleFix":"// before\nval idx = s.indexOf(\"=\") // throws when \"=\" absent\n// after\nval idx = s.indexOfOrNull(\"=\") ?? -1","handlingStrategy":"fallback","validationCode":"// Pkl\nif (s.contains(pattern)) s.indexOf(pattern) else -1","typeGuard":"function hasPattern(s: String, p: String): Boolean = s.contains(p)","tryCatchPattern":"try { s.indexOf(p) } catch (e: PklError) { -1 }","preventionTips":["Prefer indexOfOrNull and handle null","Check contains() before indexing","Normalize case/whitespace between string and pattern","Use null-coalescing (??) to supply default indices"],"tags":["pkl","string","pattern-not-found"],"backgroundTag":"resource-not-found","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}