{"record":{"id":"13cbf75636c93f98","repo":"apple/pkl","slug":"path-spec-pathspec-contains-illegal-character","errorCode":null,"errorMessage":"Path spec `$pathSpec` contains illegal character `${pathSpec[illegal]}`.","messagePattern":"Path spec `\\$pathSpec` contains illegal character `(.+?)`\\.","errorType":"validation","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"pkl-cli/src/main/kotlin/org/pkl/cli/OutputUtils.kt","lineNumber":27,"sourceCode":" *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.pkl.cli\n\nimport java.io.OutputStream\nimport org.pkl.commons.cli.CliException\nimport org.pkl.core.util.IoUtils\n\nfun checkPathSpec(pathSpec: String) {\n  val illegal = pathSpec.indexOfFirst { IoUtils.isReservedFilenameChar(it) && it != '/' }\n  if (illegal == -1) {\n    return\n  }\n  throw CliException(\"Path spec `$pathSpec` contains illegal character `${pathSpec[illegal]}`.\")\n}\n\nfun OutputStream.writeText(text: String) = write(text.toByteArray())\n\nfun OutputStream.writeLine(text: String) {\n  writeText(text)\n  writeText(\"\\n\")\n}\n","sourceCodeStart":9,"sourceCodeEnd":36,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-cli/src/main/kotlin/org/pkl/cli/OutputUtils.kt#L9-L36","documentation":"checkPathSpec validates user-supplied output path specs (patterns used with multi-file output) before any files are written. If the spec contains a character that IoUtils considers reserved/illegal in filenames (other than the allowed '/'), it throws CliException naming the offending character. This prevents generating files with names the OS cannot represent or that could escape the output directory.","triggerScenarios":"Calling writeMultipleFileOutput / passing a --output-path pattern (e.g. with globs or templating) that includes characters like ':', '*', '?', '\"', '<', '>', '|', or control characters, when running `pkl test --junit-dir` style or project output commands that write multiple files.","commonSituations":"Copying a Windows-style path with drive colon into a path spec; embedding a glob asterisk where it is not allowed; template placeholders producing characters like '?' or quotes; shell quoting mangles the spec before Pkl sees it.","solutions":["Remove or replace the illegal character reported in the message; keep only legal filename characters and '/'.","Quote the path spec properly in your shell so Pkl receives the intended characters.","If you need directory structure, use '/' separators rather than OS-specific separators or reserved chars."],"exampleFix":"// before\nval spec = \"out: @{name}.xml\"\n\n// after\nval spec = \"out/@{name}.xml\"","handlingStrategy":"validation","validationCode":"// reject specs containing characters outside [A-Za-z0-9._@{}-/] before invoking the CLI\nfun isSafePathSpec(spec: String) =\n  spec.all { it.isLetterOrDigit() || it in \"._-/@{}\" }","typeGuard":"fun String?.asSafePathSpec(): String? =\n  this?.takeIf { it.isNotEmpty() && it.none { c -> IoUtils.isReservedFilenameChar(c) && c != '/' } }","tryCatchPattern":"try {\n  writeMultipleFileOutput(pathSpec, ...)\n} catch (e: CliException) {\n  if (e.message?.contains(\"illegal character\") == true) {\n    println(\"Fix your --output-path spec: ${e.message}\")\n  } else throw e\n}","preventionTips":["Build path specs from safe character sets only; use '/' for directory structure.","Quote path specs in shell scripts to prevent mangling.","Avoid embedding OS-specific separators (backslash, drive colon) in specs."],"tags":["cli","path-spec","validation","filename"],"backgroundTag":"invalid-argument-format","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}