Troubleshooting
On this page
When bizzpocket build (or dev) fails, the message starts with an error code and ends with a
link to this page:
NO_BLOCK_FILE: blocks/hello: no hello.tsx and no non-'use client' .tsx file — see docs/theme-sdk/troubleshooting.md#no_block_fileFind the code below. Every code has what it means and how to fix it. The anchor is the code in lowercase.
One build reports every problem it finds, not just the first. With more than one, the message
starts with N build errors: and lists them, each with its own code and link; the code at the very
front is the first one's.
- Build errors
- Registry errors (
add,diff) - Messages that have no code
- It builds, but something is wrong
Build errors
Finding your theme and blocks
NO_CONFIG
Cause. The theme folder has no theme.config.ts. (.tsx, .mts, .js and .mjs also work.)
Fix. Create one with export default theme({ id, name, tokens }), or run bizzpocket build from the
theme folder (or pass --dir). See theme-config.md.
NO_BLOCKS_DIR
Cause. There is no blocks/ folder in the theme.
Fix. Create blocks/ and put one folder per block in it. Check that you are in the right folder.
NO_BLOCK_FILE
Cause. A folder in blocks/ has no block file: there is no <folder>.tsx, and no other .tsx file
that does not start with 'use client'.
Fix. Name the block file after the folder: blocks/product-grid/product-grid.tsx. Remove empty
folders.
AMBIGUOUS_BLOCK_FILE
Cause. The folder has no <folder>.tsx and has two or more other server .tsx files, so the build
cannot tell which one is the block.
Fix. Name the block file after the folder (product-grid.tsx). Other helper files may stay.
NOT_A_BLOCK
Cause. The block file exports no block({ ... }). Often a missing export default, or the default
export is a plain component. The message is blocks/<name>: no block() definition exported.
Fix. Make the file export default block({ name, render, ... }).
INVALID_BLOCK_NAME
Cause. A folder name in blocks/ is not lowercase-kebab. Only a to z, digits and dashes are
allowed, starting with a letter.
Fix. Rename the folder: ProductGrid or product_grid becomes product-grid.
DUPLICATE_BLOCK_IDENT
Cause. Two block folders give the same internal name once dashes are removed, such as hero-2 and
hero2.
Fix. Rename one of the folders.
Theme files
INVALID_PACKAGE_JSON
Cause. package.json is missing, or has no name or no version.
Fix. Add "name" and "version" (for example "0.1.0"). bizzpocket init creates both.
PARSE_FAILED
Cause. A source file has a syntax error. The message names the file and the problem (an unclosed tag, a stray brace...). Fix. Fix the syntax in that file.
INVALID_THEME_ID
Cause. The theme id is not lowercase-kebab. Also raised by bizzpocket init <dir> when the folder
name is not (init Bad_Name).
Fix. Use a name like my-theme: lowercase letters, digits and dashes, starting with a letter.
THEME_ID_MISMATCH
Cause. The build reads the theme's id from theme.config.ts without running it, and it found a
different value than the one the config really has. This happens when id is not written as a plain
string (for example id: THEME_ID).
Fix. Write id as a string literal: theme({ id: 'my-theme', ... }).
INVALID_MANIFEST
Cause. The theme's settings failed validation. The message lists each problem as path: reason.
Common causes:
version: theme version must be valid semver: theversioninpackage.jsonis not like1.2.3.defaultLayouts.<name>: Invalid key in record: a file inlayouts/is not named after a page type (home.json,product.json... orglobal.json). Rename or remove it.- A token name has characters other than letters, digits,
-and_, or a token value is not a safe CSS value. style "x" sets token "y", which is not in the manifest's overridable list.- More than 5
styles, or aswatchthat is not 3 or 4 hex colours.
Fix. Fix what the message names. See theme-config.md.
INVALID_LAYOUT_JSON
Cause. A file in layouts/ is not valid JSON, or is not a JSON object.
Fix. Open the file named in the message and fix the JSON (a missing comma or brace; no comments
allowed).
NO_GLOBAL_LAYOUT
Cause. There is no layouts/global.json, and layouts/home.json has no header block and footer
block to build one from.
Fix. Add layouts/global.json:
{ "schemaVersion": 2, "regions": { "header": [ ... ], "footer": [ ... ] } }. See
theme-config.md.
INVALID_CATALOG
Cause. The editor catalogue (blocks.json) the build made did not pass validation. The message lists
the problem, such as blocks.0.category: Invalid option or blocks.0.role: Invalid option. Usually a
block's category or role is not one of the allowed names.
Fix. category must be one of header, footer, hero, products, collections, content,
media, social-proof, promo, commerce, account, utility. role must be one of the roles in
theme-config.md. The number in blocks.0 is the position of the block
in the alphabetical list of block folders.
Building
UNRESOLVED_DEPENDENCY
Cause. An import could not be resolved. Either:
- your theme imports an npm package that is not installed (
Could not resolve 'swiper' in blocks/hero/hero.tsx ... Install swiper in the theme), or a relative file that does not exist; or - the CLI could not find one of the packages it provides to every theme (
@bizzpocket/theme,@bizzpocket/theme-sdk,react,react-dom,zod) in its own install.
Fix. For a theme package: bun add <package> in the theme folder. For a file: check the path and
the extension. For the CLI's own packages: reinstall the CLI (bun install in the theme, or reinstall
@bizzpocket/cli); these always come from the CLI, never from your theme's node_modules.
BUNDLE_FAILED
Cause. The bundler could not build your code. The message holds the bundler's own explanation (file and line). Fix. Read the first line of the message and fix the code there.
UNSUPPORTED_OPTION
Cause. The build was called with an out option other than <theme>/dist. The command line has no
such option. It can only come from code that calls the build function.
Fix. Remove the option. The output always goes to dist/.
CSS_FAILED
Cause. A CSS file has an error the CSS compiler cannot recover from (an unclosed brace, an invalid
media query, an empty selector). The message gives file:line:column.
Fix. Fix the CSS at that position.
STYLES_EXPORT_MISSING
Cause. package.json does not export the built stylesheet, which the storefront needs. Common after
bizzpocket migrate, because the old theme points ./styles somewhere in src/.
Fix. Add this to package.json:
"exports": { "./styles": "./dist/styles.css" }UNKNOWN_DEFAULT_VARIANT
Cause. theme.config.ts sets defaultVariants: { <type>: '<id>' }, but no block of that type has
that variant id. The message lists the variants the type does have (or says no block has that type).
Fix. Use one of the listed ids, or fix the block's variant (or its type). See
theme-config.md.
MIGRATE_INCOMPLETE
Cause. bizzpocket migrate could not convert every variant of the 2.x manifest (for example a
defineBlock whose variant id is not a plain string, or a module it could not transform). A real run
refuses to write a theme that would lose blocks, so nothing was written. The message lists the
type|variantId pairs it would drop.
Fix. Run bizzpocket migrate --dry-run to see the report and notes, make the listed blocks
recognisable (a literal variant.id, one defineBlock per module), then run it again. See
migrate.md.
Islands
See interactivity.md.
CLIENT_IMPORT_FORBIDDEN
Cause. A 'use client' file imports @bizzpocket/theme-sdk (or one of its sub-paths) or zod.
Those are server tools, large, and must not be sent to the browser. The message names the file and the
import.
Fix. Remove the import from the island. Keep schemas and SDK calls in the block file, and pass the
island plain data as props. Islands can use React, @bizzpocket/theme/client and any npm package.
NON_SERIALIZABLE_ISLAND_PROP
Cause. A block passes a function, a class, a new X() instance or a JSX element as a prop to a
'use client' component, for example <Slider onChange={() => ...} />. Props are sent to the browser
as JSON, so they can only be strings, numbers, booleans, null, arrays and plain objects.
Fix. Move the logic into the island and pass data. Instead of <Gallery render={(i) => ...} />,
write <Gallery images={images} /> and render inside Gallery.
UNSUPPORTED_CLIENT_EXPORT
Cause. A 'use client' file uses export * from '...', or exports a name that is not a plain
identifier.
Fix. Export each component by name: export { Slider } from './slider', or define it in the file.
DUPLICATE_ISLAND
Cause. Two 'use client' files of one block have the same name apart from the extension, such as
slider.ts and slider.tsx, or a block imports a 'use client' file from outside its folder (say
components/slider.tsx) with the same name as one in its folder. They would get the same island id
(<block>/<file name>).
Fix. Rename one of them.
CLIENT_HOOK_IN_SERVER
Cause. Code that runs on the server uses something that only works in the browser: a client-only
React API (useState, useEffect, useRef, useContext, createContext, startTransition,
useFormStatus, createPortal, requestFormReset...), a class that extends Component, anything
from @bizzpocket/theme/client or react-dom/client, or theme-sdk's 2.x <Client> marker. On the
Next host blocks render as React Server Components, where these do not exist, so the block would
throw there. The check follows the block file and every theme module it imports (through barrels
such as export { useState } from 'react' too), and stops at 'use client' files. The message names
the block, the file and the API, and lists every block that has the problem.
Fix. Move the interactive part into a 'use client' file and render that from the block (see
interactivity.md). After bizzpocket migrate, this is the hand-fix list of
blocks the report marks broken.
Registry errors
These come from bizzpocket add and bizzpocket diff. They print as CODE: message. See
registry.md.
REGISTRY_NOT_FOUND
Cause. The registry package @bizzpocket/blocks could not be downloaded: the address is wrong, you
have no access, there is no network, or your token was withheld (a warning printed just above says so
and names the variable).
Fix. Check the @bizzpocket:registry= line in .npmrc. If a warning said your token was ignored,
see Security: who gets your token (--trust-registry,
--allow-proxy, or unset the proxy/CA variable).
UNKNOWN_ITEM
Cause. add <name> asked for something that is not in the registry.
Fix. Check the spelling. The current items are listed in registry.md.
MODIFIED_FILE
Cause. add would overwrite a file that you changed since you installed it.
Fix. Run bizzpocket diff <name> to see your changes. To replace the file with the registry's
version, run bizzpocket add <name> --overwrite.
UNSAFE_PATH
Cause. A file to write is not safe: its path leaves the theme folder, passes through a symlink,
is a directory, has a reserved Windows name (con, nul, aux...), ends in . or a space, or its
parent folder does not exist.
Fix. Look at the path in the message. Replace a symlink with a real folder. If the item name itself
is the problem, the registry is damaged: report it.
INVALID_REGISTRY
Cause. The registry data is malformed (a bad item, no registry.json, a failed checksum, a file
missing from the package), or your .npmrc is unsafe: it names an environment variable other than
NPM_TOKEN, BIZZPOCKET_NPM_TOKEN or VERDACCIO_TOKEN (.npmrc may only reference those three), the registry address contains ${...}, or
the address is not a valid URL. The variable check only runs on the token line the CLI is about to send, so the
error appears only when that token would really be used.
Fix. For .npmrc problems, fix the file as the message says. For checksum or content problems,
retry later; if it persists the published package is broken, so report it.
NOT_INSTALLED
Cause. diff <name> was given a name that this theme never installed with add.
Fix. Run bizzpocket diff with no name to see all installed items, or add it first.
INVALID_LOCK
Cause. bizzpocket.json is not valid or has an unexpected shape.
Fix. Fix the JSON. If you cannot, delete the file and re-run add for your items (use --overwrite
for files you want to reset).
INVALID_FLAG
Cause. A command-line flag is wrong. For example --trust-registry has no value, or its value is
not a bare host name (https://registry.example.com or registry.example.com:4873 are refused).
Fix. Pass only the host name: --trust-registry registry.example.com.
Messages that have no code
A few errors come from the author API while your theme loads, so they are plain messages without a code.
| Message | Fix |
|---|---|
Block "X" sets both data and load; they are mutually exclusive. |
Use one. See data.md. |
Fields "a" and "b" are both spacing traits; a block can have only one per kind. |
A block may have one f.spacing(), one f.colorScheme() and one f.typography(). |
style "x" sets token "colors.primary", which is not in the theme's overridable list |
Add the path to overridable. See theme-config.md. |
BIZZPOCKET_DEV_TOKEN is not set... |
No token: run dev --mock instead (sample data, no store). With --store, dev needs that store's developer token (bpdt_…) in your shell; the store owner creates it in Settings → Developers. Never print or commit it. See first-block.md and tokens.md. |
dev --store pages fail with page endpoint responded 401 |
The developer token was revoked, has expired, or was mistyped. Run bunx bizzpocket whoami --store <slug> to see which; ask the store owner for a new token. |
page endpoint responded 403 with a developer token |
--store is not the store the token was made for. whoami prints the right slug. |
page endpoint responded 429 |
More than 120 requests a minute with one developer token. Wait a minute; avoid reload loops. |
--api must be https (plain http only for localhost) |
Use an https:// address for --api. |
dev needs --store <slug> (or --mock ...) |
Add --store <your-store-slug>, or --mock for sample data. |
--mock serves sample data: drop --store / --api |
--mock uses its own data; pass either --mock or --store, not both. |
blocks/x/x.tsx does not exist (add-to-layout) |
The name is the block's folder under blocks/. Create the block first. |
<dir> is not empty; init only creates a theme in a new or empty directory |
Pick a new folder name for init. |
init needs exactly one of --from <themeDir> or --blank |
Use init <dir> (blank) or init <dir> --from <theme>. |
It builds, but something is wrong
My block does not appear on the page.
It is not in the page's layout. Add it to layouts/<page>.json with "type" set to the block's folder
name. Also check that the block returns something: render returning null shows nothing (for
example when data() found no products).
My interactive component does nothing.
Check that its file's first statement is 'use client'. The file may live in the block's folder or
anywhere else in the theme (components/), as long as the block (or a server file it imports) imports
it. Without the directive it renders as plain HTML and never becomes interactive. See
interactivity.md.
My island isn't clickable straight away.
Islands wake up when they come close to the screen (hydrate: 'visible', the default), or after about
5 seconds. Until then the server HTML is there but clicks do nothing. For something that must work as
soon as the page loads (a header menu, a cart button), set hydrate: 'load' on its block. See
interactivity.md.
My drawer, modal or event listener reacts late (or only after a few seconds).
An island that renders nothing visible (a closed drawer, a modal, a component that only listens for
events) is never "near the screen". The runtime notices that its elements have no size and wakes it
when the browser is next idle, but an island that renders no element at all, or that must react to the
very first click, should set hydrate: 'load' on its block.
The data column says runtime, I wanted static.
Read the why runtime line under the table: it names the file, the line and what stops the block being
static. Each reason and its fix: Why is my block runtime?.
The blocks inside my group do not show.
On the Bun runtime (bizzpocket dev), check the dev log: a child the container's allow does not accept,
children past max, or nesting deeper than 3 levels are skipped with a line naming the block id. In the
layout, the children must be under the container node's children. On the Next host, containers render
empty until host item 25 lands. See group.md.
The data is null in render.
A required argument was empty, the store has nothing for it, or the fetch failed. Always handle null
(data.md). In dev, check the store slug and that the collection or
product handle exists in that store.
A field shows up with an odd label ("Cta href").
Labels are made from the key. Set label: 'Button link' (fields.md).
An image does not show.
Image and f.image() accept only https: URLs and paths that start with a single /. http:,
data: and //host/... are dropped.
A link does nothing / has no href.
Link drops unsafe hrefs: only /path, #anchor, https:, mailto: and tel: are kept.
dev shows "forbidden host" or "forbidden origin".
The dev server only answers on localhost, 127.0.0.1 or [::1], on its own port, and only
for GET and HEAD. Open http://127.0.0.1:4321 (the address dev prints).
dev shows a red bar and stays on the old page.
The last save did not build. The message in the bar is the build error. Fix it and save again. The
last good build keeps serving meanwhile.
The client gz number is large.
A 'use client' file imports a big package. The size report shows the total per block. Import less, or
do the work on the server.
I do not know what a build wrote.
Look in dist/: size-report.json, templates.json (data templates), blocks.json (editor
catalogue), bun/ (the Bun bundle) and index.js, index.d.ts, styles.css.