Troubleshooting
Every error Takumi prints, what to do about it, and why it happens.
Each heading below is the text an error prints. Search this page for the line your build or your server printed.
Pick the right entry
Most build failures are a target reading the wrong entry. Start here.
| Target | Import |
|---|---|
| Node.js, Bun, Deno, Cloudflare Workers | takumi-pdf / takumi-js |
| A Next.js route, either runtime | takumi-pdf/next |
| A browser or web worker bundle | takumi-pdf/no-init plus takumi-pdf/wasm-url |
| A browser bundle, image output | takumi-js/wasm/no-init plus takumi-js/wasm-url |
The default entry reads the export conditions your bundler sets. It covers every server runtime with no configuration.
Bundler errors
Export default doesn't exist in target module
Load the binary yourself:
import init, { render } from "takumi-pdf/no-init";
import wasmUrl from "takumi-pdf/wasm-url";
await init({ module_or_path: wasmUrl });takumi-js takes the same pair: takumi-js/wasm/no-init and takumi-js/wasm-url.
Your browser bundle resolved the Vite entry. Vite, webpack, and Turbopack set the
same conditions for a browser build, and that entry loads the binary through a
?url import only Vite reads.
non-ecmascript placeable asset
Keep @takumi-rs/core out of the bundle:
const config: NextConfig = {
serverExternalPackages: ["@takumi-rs/core"],
};The package holds a native .node addon, which no bundler can inline.
takumi-pdf needs no entry here, because it is WebAssembly only.
Cannot find module '@takumi-rs/core-42dc295dcb05a7ef'
Add the serverExternalPackages entry above, then delete .next and start again.
This is the same native addon in dev mode. Turbopack rewrote the specifier to an internal id, which Node cannot resolve at runtime.
Cannot find native binding
@takumi-rs/core loads a platform-specific native package, and the one for the
current platform is missing. Two things cause that.
Hoist the native package
A package manager with a virtual store, such as pnpm or Yarn, has to be told to
hoist the native binary. Re-run pnpm i after the change.
publicHoistPattern:
- "@takumi-rs/core-*"With pnpm older than 10.5.0, put the equivalent setting in .npmrc instead:
public-hoist-pattern[]=@takumi-rs/core-*Install the package for your deploy target
Package managers install the native package for the machine running the install, so installing on macOS and deploying to Linux leaves the target's package missing. Install it explicitly:
npm install @takumi-rs/core-linux-x64-gnu| Target | Package |
|---|---|
| Linux x64 (glibc) | @takumi-rs/core-linux-x64-gnu |
| Linux x64 (musl, Alpine) | @takumi-rs/core-linux-x64-musl |
| Linux arm64 (glibc) | @takumi-rs/core-linux-arm64-gnu |
| Linux arm64 (musl) | @takumi-rs/core-linux-arm64-musl |
| macOS x64 | @takumi-rs/core-darwin-x64 |
| macOS arm64 | @takumi-rs/core-darwin-arm64 |
| Windows x64 | @takumi-rs/core-win32-x64-msvc |
| Windows arm64 | @takumi-rs/core-win32-arm64-msvc |
Module not found: Can't resolve './takumi_pdf_wasm_bg.js'
On Turbopack, drop the rule that asks for this:
const config: NextConfig = {
turbopack: {
rules: { "*.wasm": { type: "wasm" } },
},
};On webpack or Rspack with target: "node", upgrade instead:
npm install takumi-pdf@latest @takumi-rs/wasm@latestThe rule asks the bundler to instantiate the binary, which sends it looking for
wasm-bindgen glue the package does not ship: the glue is compiled into dist,
and pkg holds the binary alone.
Module parse failed: Unexpected character '\0'
Upgrade, then build again:
npm install takumi-pdf@latest @takumi-rs/wasm@latestRspack parsed the binary as JavaScript, for the same reason as above.
ENOENT: no such file or directory, open '.../pkg/takumi_pdf_wasm_bg.wasm'
Mark the package external for that build:
esbuild.build({ external: ["takumi-pdf"] });esbuild, Rollup, and Bun's bundler flatten the Node entry into one file and leave
its new URL(specifier, import.meta.url) call alone, so the path lands next to
the output instead of inside node_modules. Vite, webpack, and Turbopack rewrite
that call and copy the binary, so they need nothing.
Unable to locate Takumi WASM asset for SSR
Keep the package external for SSR:
export default { ssr: { external: ["takumi-pdf"] } };Vite writes the client asset and the server chunk to different directories, and the entry searches the usual layouts for it. External skips the search entirely. If your framework has to bundle it, open an issue with the output layout.
Render errors
No registered font covers क (U+0915)
Register a font covering the characters the error names:
import { googleFonts } from "@takumi-rs/helpers";
import { render } from "takumi-pdf";
const pdf = await render(document, {
fonts: await googleFonts(["Noto Sans Devanagari"]),
});Those characters would draw nothing and leave nothing in the text layer, so the render stops rather than shipping a page with holes.
A PDF cannot draw filter: blur(2px)
Drop the filter, or rasterize that subtree yourself and place it as an <img>.
PDF has no blur operator, so blur() and drop-shadow() cannot be drawn.
Dropping them quietly would ship a page that disagrees with the image output.
An error occurred while decoding the image data
Re-encode the image as PNG, JPEG, or WebP.
Those three embed directly. GIF has no decoder in this build. A CSS filter
needs pixels to work on and only PNG decodes for that path, so an image under a
filter raises this too when it arrived as JPEG or WebP.
The content spans more than 20000 pages
Give the tree a height that resolves. A percentage height inside a paged render has nothing to resolve against, so the content grows until the page cap stops it.
Node.js
TypeError: fetch failed
Pass the image as a base64 data URL, which skips the fetch.
Node's fetch, through undici, can drop the
socket while loading a remote img URL
(#349).
Layout
The layout is not what I expected
Set drawDebugBorder to outline every node:
import { ImageResponse } from "takumi-js/response";
export function GET() {
return new ImageResponse(<></>, {
width: 100,
height: 100,
drawDebugBorder: true,
});
}If the outlines look right and the render still does not, file an issue.
Last updated on