---
title: Troubleshooting
description: The failures that waste an afternoon, what actually causes them, and the check that tells them apart.
updated: 2026-07-26
---

Most Quilium problems are one of a dozen, and almost none of them say what they are. This page maps the symptom to the cause.

<div class="q-callout q-callout-note"><i class="fa-solid fa-flask lead"></i>
  <div><b>Live examples.</b> Every case below happened while building the demo sites used throughout this documentation, and the fix is the one that worked.</div></div>

## The page returns 404

| Check | If it is that |
|---|---|
| Is the page `state: inactive`? | An inactive page 404s **everywhere**, locally included. "Draft" never means inactive. Set it back to active. |
| Does the route exist, and does its `path` start with a slash? | A path without it glues to the page URL and matches nothing: `{{article.slug}}` on a page at `/article` gives `/article<slug>`. |
| Is it a detail page? | Its page must exist, be hidden rather than deleted, and use the detail page-type. |
| Is it the 404 template itself failing? | `miscellaneous.rendering.404` must point at a template that exists, extension included. |

## The page renders empty, with no error

The template ran and produced nothing, which almost always means the data was not where you looked.

- A collection item's fields are under **`data`**, a content block's under **`custom`**. Reading the wrong one returns blank, not an error.
- A query's results live on the object that declares it: `page.custom.<queryKey>` for a page-type query, `content.custom.<queryKey>` for a block query.
- `route.*` **only exists inside a query config**. In a template it silently resolves to nothing.

When it stays mysterious, probe instead of theorising:

```liquid
<!--DBG articles=[{{ articles.size }}] first=[{{ articles[0].data.title }}]-->
```

Then `curl <url> | grep DBG` and delete the line. Some filters return empty without erroring, and guessing which one is slower than looking.

## A write returns 422

| Cause | Fix |
|---|---|
| Wrong wrapper | `update-content` writes under `custom:`, `update-itemset-item` under `data:`. |
| A reference sent as a string | Images and files are arrays of objects, `[{id: '<uuid>'}]`; items and page references are flat arrays of ids, `['<uuid>']`. Never a bare string. |
| A translation-only payload | Send the main data plus **one** locale per call, never a translation alone. |
| `UniqueUrl` on publish | Two pages resolve to the same URL, typically a detail child with an empty slug. Give it a real slug, or uncheck the parent prefix on the child. |

## A settings write silently does nothing

`update-settings-partial` requires `target` to be the **top-level key** of the YAML you send. A mismatch fails without a warning. And a `replace` sends the whole block: read it, merge, write it back entire, or you delete the fields you left out.

## Translations do not show up

- The interface string must be a **literal**: `{{ 'Read more' | _ }}` is extracted, `{{ label | _ }}` is not.
- Extraction is a step, not magic. Run `quilium dictionary parse` (or `quilium push`, which runs it), then fill the translations.
- A field that is not `translatable: true` in its type will never carry a second locale.

## The live site does not match my machine

Push moves templates, publishing moves content. Doing one and expecting the other is the single most common surprise.

```bash
quilium push
```

Then publish the pages. See [Publish and go live](/en/docs/publish-and-go-live).

## The CLI refuses to work

| Symptom | Cause and fix |
|---|---|
| `quilium run` says local files are missing | You are in a folder with no theme. Run `quilium pull`. |
| `pull` refuses to run | `public/` is not empty. Back it up, or use `--force`, which replaces everything. |
| `push` refuses | `public/` is empty. Pushing an empty theme would blank the site. |
| A 403 mid-command | Wrong account or expired session. `quilium whoami` answers it in one call. |
| Endpoints behave oddly | Check `quilium.json` for a local override that travelled up on a push. |

## A block renders as a 500, or not at all

| Symptom | Cause and fix |
|---|---|
| `ENOENT: Failed to lookup "elements/<key>.html"` | The content-type has no `template:` key, so the engine looked for `<key>.html`. Only `.liquid` loads. Add `template: 'elements/<key>.liquid'`. |
| The `template:` key is there and the error still names `.html` | **A content block freezes its template when it is created**, exactly as a page freezes its page-type. Fixing the YAML does not reach blocks that already exist — delete the block and add it again. |
| A block silently loses its data halfway through a loop | An `{% include %}` shares the caller's scope. A partial that does `{% assign c = … %}` overwrites the caller's `c` — and almost every element file opens on `{% assign c = content.custom %}`. Name partial-local variables after the partial. See [Reuse blocks](/en/docs/reuse-partials). |
| An external feed's block is empty, page returns 200 | A failed `api` fetch yields an empty object, silently. See [Consume an external feed](/en/docs/external-feed). |

## The agent did something unexpected

- It deactivated pages because it was told to keep them "in draft". Say "leave them unpublished", never "deactivate".
- It filled a collection and the entries went live immediately. Entries have no draft state; only pages do. See [Publish and go live](/en/docs/publish-and-go-live).
- It invented a structure because it never read the site. Make `get-skills` then `get-site-settings` the first two calls of the session, see [Prompting well for Quilium](/en/docs/prompting).
- It reported "done" without checking. Ask for the verification output, not the summary.

## Related

<div class="q-cards">
  <a class="q-card reco" href="/en/docs/cli"><span class="k">Recommended</span><span class="t">Quilium CLI</span><span class="d">Every command, flag and config key.</span></a>
  <a class="q-card" href="/en/docs/mcp-tools"><span class="t">MCP tools</span><span class="d">Write shapes and the gotchas behind 422s.</span></a>
  <a class="q-card" href="/en/docs/routing-and-urls"><span class="t">Routing and URLs</span><span class="d">Why a detail page resolves the way it does.</span></a>
</div>
