Skip to content

Conversation

@cderv
Copy link
Collaborator

@cderv cderv commented Oct 30, 2025

When rendering with --output-dir on Windows without a project file, Quarto would fail with:

ERROR: os error 32: remove 'path\.quarto'

Root Cause

When --output-dir is used without a project file, Quarto creates a "synthetic" project context with a temporary .quarto directory to manage the render. The issue was a timing problem in cleanup ordering:

  1. Rendering completes
  2. Code tries to remove .quarto directory
  3. But the Deno KV database file inside .quarto is still open
  4. context.cleanup() (which closes the KV file) is called later by the caller
  5. Windows doesn't allow deleting open files → error 32

Fix

Call context.cleanup() before attempting to remove the .quarto directory. This ensures file handles are properly closed first.

The fix is minimal (5 lines) and safe because cleanup() is idempotent (wrapped with once()), so calling it early and again later has no side effects.

Alternative Approach Considered

Initially implemented a path registration mechanism where code could register paths for cleanup at the point of decision. This added cleanupPaths array and registerForCleanup() method to ProjectContext, with cleanup logic duplicated across 4 locations.

This was deemed too complex for a single use case (82 lines across 6 files). The simpler ordering fix achieves the same result.

Documentation

Added comments explaining the "synthetic project" pattern:

  • When --output-dir is used without _quarto.yml, Quarto creates a temporary project context
  • The forceClean flag signals this is temporary and needs cleanup
  • Creation: src/command/render/render-shared.ts:52-58
  • Cleanup: src/command/render/project.ts:889-907

Added tests in tests/smoke/render/render-output-dir.test.ts covering both default cleanup behavior and --no-clean flag preservation.

Fixes #13625

This should also probably be backported as this is common problem, and could explain quarto preview lock issue in positron (which I think use --output-dir for some files)

cderv added 8 commits October 30, 2025 11:52
When --output-dir is used without a project file, Quarto creates a
synthetic project context with a temporary .quarto directory to manage
the render. This fix ensures file handles are closed before attempting
to remove the directory, preventing Windows "os error 32" (file in use
by another process).

The synthetic project pattern:
- Triggered when: quarto render file.qmd --output-dir output/ (no _quarto.yml)
- Creates temporary .quarto directory in current directory
- Uses full renderProject() path (not singleFileProjectContext())
- forceClean flag in RenderOptions signals cleanup needed
- After render: close handles (context.cleanup()) then remove directory

Improved comments to explain the synthetic project pattern, the dual
purpose of the forceClean flag, and critical ordering requirements to
avoid file locking issues on Windows.

Fixes #13625
@posit-snyk-bot
Copy link
Collaborator

posit-snyk-bot commented Oct 30, 2025

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Licenses 0 0 0 0 0 issues
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

cderv added a commit that referenced this pull request Oct 30, 2025
Backport Windows file locking fix for --output-dir to v1.8

Fixes "os error 32" on Windows when rendering with --output-dir flag
outside of a project. Ensures file handles are closed before removing
the temporary .quarto directory.

Backport of #13626 to close #13625
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows file locking issue when --output-dir is used on single file render (non project context)

3 participants