Troubleshooting
unipress surfaces actionable failures at install and compile time — each names a class and a cause. This file pairs each with what it usually means and how to fix it.
Every unipress compile error exits with code 1 (user-addressable). Unknown errors exit with code 2 — those are internal bugs; re-run with --verbose and open an issue.
Homebrew: Error: Refusing to load formula ... from untrusted tap uniweb/unipress
Recent Homebrew (6.x) won't load a formula from a third-party tap until you've trusted it once. This blocks both the first brew install uniweb/unipress/unipress and later brew upgrade unipress.
Trust the tap once, then re-run the command:
brew trust uniweb/unipress
brew upgrade unipress # or: brew install uniweb/unipress/unipressThis is a Homebrew policy for third-party taps, not specific to unipress. The npm install (npm i -g @uniweb/unipress) and the prebuilt binaries on the releases page are unaffected.
ContentDirectoryError: content directory does not exist: <path>
The positional argument to unipress compile is wrong. Check your cd and the spelling. Paths are relative to the current working directory.
DocumentYmlError: no document.yml (or site.yml) found in <path>
unipress expects a top-level config file inside the content directory.
If the folder already holds markdown, you don't have to write one by hand — compile offers to generate it. Running interactively, it prompts:
$ unipress compile .
No document.yml here. Generate one (A4 article, pdf) from the 12 markdown files at the project root and compile? (Y/n)
Document title › My Document
created /path/to/document.ymlBy default this produces a clean single-column article (A4, no chapters). Pass --yes to skip the prompt (handy in scripts or non-interactive shells):
unipress compile . --yes # generate + compile → A4 article PDF
unipress compile . --yes --foundation @unipress/data@0.1.1 --format docxThe generated document.yml pins a foundation, sets the format, lists the sections in reading order, and — when the markdown sits loose at the project root rather than under content/ — points the content directory at the root with paths: { pages: . }. It's an ordinary config file; edit it freely.
To write one by hand instead:
foundation: "@unipress/book@0.4.3"
format: pdf
paths:
pages: . # only needed when sections live at the root (no content/ folder)
book:
kind: article # single-column paper; omit for a chaptered book
trim: a4 # or: letter
content: [introduction, main]site.yml is accepted as a fallback if you're dogfooding an existing Uniweb site.
DocumentYmlError: <config> has no pages — nothing to compile
A config file exists, but the collector found no chapters. The usual cause is markdown living somewhere the document profile didn't scan — loose at the project root while the profile looks under content/. The error names the fix; for root-level files, add paths: { pages: . } to your document.yml.
DocumentYmlError: malformed YAML in document.yml at <file>:<line>:<col>
Fix the YAML. Common causes: unquoted strings containing :, unclosed brackets, inconsistent indentation, tabs mixed with spaces.
Note:
@uniweb/build's content collector currently catches YAML errors internally, logs[content-collector] YAML parse error: ...as a warning, and proceeds with an empty config. You'll typically see a downstream error like "no format specified" or "no foundation specified" — the YAML warning in the log is the real cause. Fix the YAML first, then re-run.
DocumentYmlError: no format specified — pass --format <fmt> or set format: in document.yml
No format is declared in the CLI, unipress.config.js, or document.yml. Pick one:
unipress compile ./my-book --format pdfOr add it to document.yml:
format: pdfThe error also lists unipress.config.js as an option when a config file is loaded.
FoundationResolutionError: no foundation specified
Set foundation: in document.yml, or pass --foundation <ref>. Four ref forms accepted:
# Registry ref (recommended) — resolved against UNIWEB_REGISTRY_URL
# or the default registry, https://uniweb.github.io/unipress.
foundation: "@unipress/book@0.1.0"
# Or a full URL.
foundation: "https://example.com/foundations/my-foundation/entry.js"
# Or a local filesystem path (relative to document.yml).
foundation: "./path/to/foundation"
# Or, inside a pnpm workspace, a bare package name (resolves through node_modules).
foundation: "@unipress/book"FoundationResolutionError: cannot find foundation package '<name>' from <dir>
The package isn't installed anywhere Node can see from the content directory. Either:
- Install it into
node_modules/locally:pnpm add <name>in the content directory (if the content dir is part of a workspace), or - Pass a local path:
--foundation ../path/to/built-foundation.
Inside a pnpm workspace, foundations linked via pnpm-workspace.yaml globs resolve automatically.
FoundationResolutionError: expected built foundation at <path>/dist/entry.js
The foundation package isn't built. From the workspace root:
pnpm --filter <foundation-name> buildunipress consumes the built artifact (dist/entry.js), not the source.
CompileError: foundation does not expose compileDocument
The foundation doesn't depend on @uniweb/press, or was built with an older @uniweb/build that predates the compileDocument re-export.
Fix: add "@uniweb/press": "workspace:*" (or the appropriate version) to the foundation's dependencies, rebuild with a current @uniweb/build (57498ef or later), and re-install.
CompileError: foundation does not declare 'outputs.<format>'
The foundation doesn't support the format you asked for. The error lists the declared formats:
error: foundation does not declare 'outputs.docx' — cannot compile.
available formats: typst, pdf, pagedjs, epubPick one of the listed formats, or pick a different foundation.
CompileError: foundation declares no outputs
The foundation is web-only — it has no outputs: map and can't be compiled as a document. Check the foundation's README to confirm it supports document output. Foundations that only drive websites can't be used with unipress.
TypstBinaryError: sha256 mismatch for typst <version>
The downloaded Typst archive doesn't match the pinned digest. Either the download was corrupted mid-transfer, or the pinned digest in src/typst/versions.js is stale.
Quick retry: delete the cache directory ($UNIPRESS_CACHE_DIR/typst/<version>) and re-run. If the mismatch persists, the pin is out of date — file an issue, or override with --typst-binary <path> pointing at a locally-installed Typst.
TypstBinaryError: typst exited with code 1
Typst rejected the foundation-generated source bundle. The error includes Typst's own stderr and a hint:
hint: pass --keep-temp to inspect the source bundleWith --keep-temp, the temp directory survives on failure. The path appears in the error:
typst exited with code 1 (temp dir kept at /var/folders/.../unipress-typst-XXXXXX)Inspect main.typ, template.typ, meta.typ, content.typ in that directory. The root cause is usually:
- The foundation's
outputs[format].getOptionsproduced a partialmetaobject missing a field the foundation's template expects. Check the foundation'scompile-options.jsagainst itstemplate.typ. - An image asset the bundle references is missing. Foundation-side: verify
gatherCovers(or equivalent) found the image at the URL it computed. - A Typst syntax issue in the foundation's preamble or template. Check against the installed Typst version (
typst --version).
OutputWriteError: failed to write output to <path>
The --out path can't be written. Most common causes: parent directory doesn't exist and unipress couldn't create it (permission denied), or the file exists and is locked by another process.
unipress creates missing parent directories automatically (like mkdir -p). If creation fails, check permissions on the destination.
ConfigValidationError: failed to load config file <path>
unipress.config.js threw during import. Common causes:
- Syntax error — Node prints
Unexpected end of inputor similar as the cause. - Missing package — if the config
import { defineUnipressConfig } from '@uniweb/unipress'and@uniweb/unipressisn't installed in that project, the import fails. Eitherpnpm add -D @uniweb/unipressin the content directory, or drop the import and use a plainexport default { … }.
ConfigValidationError: config file <path> must default-export an object
The config file's default export is a string, number, array, or something else. It must be an object:
export default { format: 'pdf' }Cover image (or other config asset) doesn't appear in the output
Not an error — a silent drop. The book compiles, but the front/back cover (or a banner/logo declared in config) is missing from the PDF/EPUB.
Config-declared asset paths — book.covers.front, book.covers.back, and the like — are resolved from the top-level config unipress reads for content collection: the default document.yml, or the file you pass to --document. They are not scanned from a unipress.config.js supplied via --config (that file layers build settings — out, format, typst — over the compile, after content is collected).
So if your covers live in document-book.yml, build it with --variant document-book — not --config document-book.yml. Confirm with --verbose: the Found N asset references line should count your covers (e.g. 2 more than the body images), and the source-bundle blob: size should grow by roughly the covers' byte size. Also confirm the files exist at the declared path relative to the content directory (e.g. assets/front.png).
Internal error (exit code 2)
Something unexpected threw — typically a library error or a code path unipress didn't wrap. Re-run with --verbose for a stack trace, then open an issue with the trace and a description of the content directory + foundation you're compiling.
unipress compile <dir> --verbose