Await which() in dependency configure guards - #14731
Open
cderv wants to merge 2 commits into
Open
Conversation
The non-vendored branch of each dependency's configure callback verifies the binary is on PATH with `if (which(file) === undefined)`. `which` is async, so this compares a Promise to undefined: always false, guard never fires. Effect: with QUARTO_VENDOR_BINARIES=false, configureDependency skips the download but still calls configure(). The guard is the only thing meant to catch a missing binary, so the build reports success and produces a Quarto tree without it. For typst-gather this surfaces only at render time, as "typst-gather analyze failed; staging all packages as fallback". Fixes the same bug in typst-gather, typst, pandoc and esbuild. Also refresh the "binary not found" message in typstGatherBinaryPath() and the dev-call command: configure.sh no longer builds typst-gather (the cargo step and package/typst-gather/ are gone; it is a downloaded release binary), and neither message mentioned QUARTO_TYPST_GATHER, which both already honour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Collaborator
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Jul 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The non-vendored branch of each dependency's
configurecallback inpackage/src/common/dependencies/verifies the binary is on PATH with:whichis declaredexport async function which(cmd: string)insrc/core/path.ts, so this compares aPromisetoundefined. A Promise isnever
=== undefined, the condition is always false, and the guard never fires.The enclosing
configureis alreadyasync, so the fix is oneawaitper site.Why it matters
When building with
QUARTO_VENDOR_BINARIES=false— which is what conda-forgedoes, so binary deps come from conda packages rather than downloaded release
assets —
configureDependencyskips the download but still callsconfigure().This guard is the only thing meant to catch "the binary is nowhere to be found".
Because it never fires, the build reports
Configuring typst-gather/typst-gather complete.and succeeds, silently producing a Quarto tree with notypst-gatherbinary at all. Confirmed against a real green CI build ofquarto 1.10.18 on conda-forge. The failure surfaces only at runtime: renders
print
typst-gather analyze failed; staging all packages as fallback: ...onevery Typst render, and
quarto call typst-gatherdies with a misleading error.The same bug is present verbatim in four dependencies, all fixed here:
package/src/common/dependencies/typst-gather.tstypst-gatherpackage/src/common/dependencies/typst.tstypstpackage/src/common/dependencies/pandoc.tspandocpackage/src/common/dependencies/esbuild.tsesbuild(
deno_dom.tsuses a synchronousDeno.env.getcheck and is unaffected;dartsass.tsanddeno.tshave noelsebranch at all, which is arguably aseparate gap and not touched here.)
Stale error message
Also refreshes the "binary not found" message in
typstGatherBinaryPath()(
src/core/typst-gather.ts) and in thedev-call typst-gathercommand. Bothsaid:
That is stale as of 1.10 —
configure.shno longer builds typst-gather (thecargo step and
package/typst-gather/were both removed; it is now a downloadedrelease binary from
quarto-dev/typst-gather). Neither message mentionedQUARTO_TYPST_GATHER, which both code paths already honour. The new messagesname the path actually checked, and distinguish "you pointed the env var
somewhere wrong" from "your install is missing the bundled binary".
Notes for reviewers
Nothing here is compile-checked or test-run. No CI workflow runs
deno checkoverpackage/src, andpackage/srchas no test coverage.Promise<string | undefined> === undefinedis TS error 2367 — a type-checkpass would have caught all four of these at build time. Adding a
deno check package/src/**step is probably the durable fix for this class ofbug, but felt out of scope here; happy to open a follow-up.
Backport. Per
dev-docs/checklist-backport-a-pr.mdthis targetsmain(1.11), with the changelog entry under
## Regression fixesto signal thebackport. The v1.10 branch is where this actually bites for packaging, so a
cherry-pick to
v1.10would be welcome.Two more instances of the same class turned up in a repo-wide scan and are
deliberately not in this PR, since each is a real behavior change worth
reviewing on its own:
src/command/render/latexmk/pdf.ts:394—if (bibCommand !== "biber" && !hasTexLive()).hasTexLiveis async, so!Promiseis always false: the Windows\bibdata{...}.bibaux-file fixup isdead code on every Windows PDF render using
bibtex.src/tools/impl/tinytex.ts:446—if (!isTinyTex())inuninstall()neverfires, so
quarto uninstall tinytexskips its "this is not a TinyTeXinstall" guard.
Say the word and I'll open a separate PR for those.
Checklist
I have (if applicable):
AI-assisted PR
src/core/path.ts(confirmedwhichisasync), the four
configurecallbacks inpackage/src/common/dependencies/, a repo-wide scan for unawaited asyncpredicates used in conditions,
dev-docs/checklist-backport-a-pr.mdand.claude/rules/changelog.mdfor branch/changelog conventions.content before submitting.