BizzPocket

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_file

Find 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

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: the version in package.json is not like 1.2.3.
  • defaultLayouts.<name>: Invalid key in record: a file in layouts/ is not named after a page type (home.json, product.json... or global.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 a swatch that 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:

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.