Common errors
The errors you'll actually see during dev and build, what they mean, and how to fix them.
~ 4 min read
Common errors
Run tangly check before you debug. Most issues that bite at build time surface there cheaply.
docs.json: “Expected … but got …”
docs.json:42 — Expected string, received boolean
at .navigation.tabs[0].groups[1].pages[2]
A nav entry is malformed. The path tells you exactly where. Common causes:
- A nested group missing
"pages": [...]. - A typo on
"group"(e.g."groups"for a single entry). - A boolean where a slug is expected (someone wrote
trueinstead of a path).
tangly check is the fastest path here. It points at the line.
”Cannot find page X referenced in navigation”
docs.json: navigation references missing page "guides/setup"
did you mean "guides/getting-started"?
The navigation has a slug for a file that doesn’t exist. Either:
- Create
guides/setup.mdx. - Update the slug to point at an existing file.
- Run
bunx tangly add page guides/setupto scaffold one.
The “did you mean” suggestion uses fuzzy matching, usually accurate.
”Broken link from X to Y”
✗ guides/billing.mdx — broken link to /reference/api/foo
An internal link points at a slug with no matching .mdx. Fix in the source page. If the slug is correct but the file moved, add a redirect to docs.json#redirects instead of changing every reference.
Astro build fails: “Failed to resolve import”
[ERROR] Failed to resolve import "../theme/Custom.astro" from "guides/foo.mdx"
A page imports a custom component that isn’t where the page expects it.
- Verify
theme/Custom.astroexists at the project root. - The import path is relative to the page file, not the project root. From
guides/foo.mdx, the path is../theme/Custom.astro, not./theme/Custom.astro.
”Image not found” / 404 on assets
Static assets (images, PDFs, video) have to live in one of the recognized roots: images/, logo/, public/, static/, assets/. Any other folder isn’t served.
- Move the file into
images/(or one of the others). - Use absolute paths (
/images/foo.png), not relative (../images/foo.png).
For the relative-path edge case: Tangly auto-rewrites  to absolute. It only works if the rewriter can resolve “the canonical asset roots”, which means non-standard locations break the rewrite. See Static assets.
Frontmatter validation warning
warning: guides/foo.mdx — frontmatter field "draft" should be boolean, got string "true"
Frontmatter is non-fatal. Your page renders, but the warning’s a sign of a bug. Fix the YAML:
draft: true # ✓ booleanNot:
draft: "true" # ✗ string“Unknown component <Foo />”
guides/bar.mdx:14 — Unknown component <Foo /> at column 1
Either:
- The component isn’t built-in (not in the components reference).
- You meant a built-in but typo’d (
<Cards>instead of<Card>). - The component is custom and you forgot to drop it in
theme/.
For built-in components: spelling counts (case-sensitive). For custom ones: drop theme/Foo.astro, restart tangly dev.
OpenAPI: “Cannot resolve $ref”
openapi.json — cannot resolve "#/components/schemas/User"
Spec references a component that isn’t in the spec. Either fix the reference or add the component. Tangly’s parser is the same oas-tools parser that production tooling uses; if it fails here, it’ll fail in production validators too.
Build is slow
Two common causes:
- Many large images. Tangly doesn’t optimize them. Pre-process with
sharporsquoosh-clibefore committing. - Huge OpenAPI spec. Splitting one large spec into per-tag files speeds builds linearly.
Otherwise builds should take under thirty seconds for a hundred pages. If you’re seeing minutes, open an issue with the build’s --debug output.
Dark mode doesn’t work
The toggle in the topbar is in theme/. If you’ve shadowed the topbar, you may have dropped the toggle.
- Check
appearance.strict: falseindocs.json(default; strict mode disables the toggle on purpose). - Verify the topbar override carries the original toggle markup.
- If you’ve overridden CSS variables, make sure
.darkselectors are present alongside the:rootselectors.
Pagefind search doesn’t return hits
Pagefind builds the index at tangly build time, not at tangly dev time. The dev modal searches a live in-memory index, so dev / prod can diverge if you’ve recently added pages.
- For dev: works automatically, no config.
- For prod: ensure
dist/pagefind/is included in your deploy. Most adapters include it; static-output deploys to S3-style hosts sometimes need an explicit copy.
Excluded pages (noindex: true, drafts) are excluded from the search index by design.
”TANGLY_USER_ROOT not set”
You’re running the runtime directly without going through the CLI. Use tangly dev / tangly build. The runtime is internal; direct invocation is unsupported.
Same errors after upgrading (stale global install)
You upgraded Tangly, but tangly check / tangly migrate keep reporting errors you already fixed. The output itself is the clue: every command stamps the version that produced it.
tangly v0.1.6
Pages: 12 Orphans: 0
If that version is older than the one you just installed, you’re running a different binary than you think. A global install (bun add -g tangly / npm i -g tangly) takes precedence on your PATH over the project-local copy, so updating the local dependency leaves the global untouched. That’s why npm list tangly can show the new version while the typed tangly command runs the old global.
Confirm and fix:
tangly --version # the version actually running (expect the old one)
npm i -g tangly@latest # update the globalOr skip the global entirely and invoke the local copy:
npx tangly checkMore
tangly checkfor config validation.- FAQ for “is this supposed to work this way?” questions.
- GitHub Issues for bugs not in either.