Bug description
On Windows, setting margin-footer (or margin-header) to inline markdown or HTML content that contains characters illegal in Windows paths causes quarto render to crash with os error 123.
This happens because websiteProjectConfig (src/project/types/website/website-config.ts) calls resolveProjectPaths on each margin-footer value, and resolveProjectPaths does a raw existsSync(maybePath) check. On Windows, existsSync throws when the string contains characters like [, ], <, >, |, :, ", ?, *.
On macOS/Linux, existsSync simply returns false for these strings, so the bug is Windows-specific.
Steps to reproduce
Create a Quarto book project with the following _quarto.yml:
project:
type: book
book:
title: "Demo"
margin-footer: |
[](https://example.com)
<link rel="preload" href="/img/logo-dark.png" as="image">
format:
html:
theme: cosmo
Then run quarto render index.qmd --to html on Windows.
Expected behavior
Quarto should render without error, treating the margin-footer value as inline markdown/HTML content (since it does not exist as a file).
Actual behavior
Render fails with:
ERROR: The filename, directory name, or volume label syntax is incorrect. (os error 123): stat '[](https://example.com)
<link rel="preload" href="/img/logo-dark.png" as="image">
Stack trace points to resolveProjectPaths in websiteProjectConfig.
Root cause
In website-config.ts:
const resolveProjectPaths = (maybePath: string) => {
if (existsSync(maybePath)) {
return join(projectDir, maybePath);
} else {
return maybePath;
}
};
existsSync should be replaced with safeExistsSync (which Quarto already uses elsewhere, e.g. in expandMarkdownFilePath) to gracefully handle invalid paths on Windows.
Workaround
Move the content to a separate file and reference it:
margin-footer: "margin-footer.md"
This works because the string is a valid file path, so existsSync succeeds, and Quarto's expandMarkdownFilePath correctly reads the file content later.
Quarto check output
Quarto 1.9.36
[✓] Checking versions of quarto binary dependencies...
Pandoc version 3.4.0: OK
Dart Sass version 1.80.5: OK
Deno version 2.2.2: OK
Typst version 0.13.0: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
Version: 1.9.36
Path: C:\Users\Andrew\AppData\Local\Programs\Quarto\bin
[✓] Checking tools....................OK
TinyTeX: (not installed)
Chromium: (not installed)
[✓] Checking LaTeX....................OK
[✓] Checking basic markdown render....OK
[✓] Checking R installation...........OK
Version: 4.5.0
Path: C:/PROGRA~1/R/R-45~1.0
LibPaths:
- C:/Program Files/R/R-4.5.0/library
knitr: 1.50
[✓] Checking Knitr engine render......OK
Your environment
- OS: Windows 11
- Quarto: 1.9.36
Bug description
On Windows, setting
margin-footer(ormargin-header) to inline markdown or HTML content that contains characters illegal in Windows paths causesquarto renderto crash withos error 123.This happens because
websiteProjectConfig(src/project/types/website/website-config.ts) callsresolveProjectPathson eachmargin-footervalue, andresolveProjectPathsdoes a rawexistsSync(maybePath)check. On Windows,existsSyncthrows when the string contains characters like[,],<,>,|,:,",?,*.On macOS/Linux,
existsSyncsimply returnsfalsefor these strings, so the bug is Windows-specific.Steps to reproduce
Create a Quarto book project with the following
_quarto.yml:Then run
quarto render index.qmd --to htmlon Windows.Expected behavior
Quarto should render without error, treating the
margin-footervalue as inline markdown/HTML content (since it does not exist as a file).Actual behavior
Render fails with:
Stack trace points to
resolveProjectPathsinwebsiteProjectConfig.Root cause
In
website-config.ts:existsSyncshould be replaced withsafeExistsSync(which Quarto already uses elsewhere, e.g. inexpandMarkdownFilePath) to gracefully handle invalid paths on Windows.Workaround
Move the content to a separate file and reference it:
This works because the string is a valid file path, so
existsSyncsucceeds, and Quarto'sexpandMarkdownFilePathcorrectly reads the file content later.Quarto check output
Your environment