Skip to main content

Common Errors & Fixes

A field guide to the errors you're most likely to hit building a Sublime app, and how to resolve each one.

Installation

npm install fails with ERESOLVE / peer dependency conflict

npm error ERESOLVE could not resolve
npm error While resolving: react-native-screens@…
npm error Could not resolve dependency: peer react-native@">=0.82.0"

Why: the React Native ecosystem pins peer dependencies strictly, and a few transitive packages (e.g. react-native-screens) demand a newer react-native than your app declares. npm's default resolver treats this as fatal.

Fix: install with legacy peer resolution — this is expected for any app with the mobile target:

npm install --legacy-peer-deps

Apps scaffolded with npm create @sublime-ui/app already run install this way.

Install hangs or fails downloading Electron

Why: the electron package's postinstall downloads a ~100 MB binary; on a slow or offline connection it stalls or fails.

Fix: skip the binary download when you only need types / aren't running the desktop app yet:

ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm install --legacy-peer-deps

Run a plain npm install later (online) when you actually want to launch the desktop shell.

ERR_MODULE_NOT_FOUND importing @sublime-ui/ui or @sublime-ui/desktop

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '.../dist/navigation/book'

Why: @sublime-ui 0.1.0 shipped ESM with extensionless relative imports, which Node's native ESM resolver rejects.

Fix: upgrade to 0.1.1 or newer, which emits correct .js specifiers:

npm install @sublime-ui/ui@latest @sublime-ui/desktop@latest --legacy-peer-deps

Storybook … must default-export a book().

Why: build:nav reads each storybook's default export. A storybook that exports its book(...) as a named const, or not at all, can't be compiled.

Fix: end every storybook.web.ts / storybook.native.ts with:

export default book({ /* … */ });

build:nav failed with N error(s); wrote nothing.

build:nav validates before generating and writes nothing if any rule fails. The diagnostics name the rule:

DiagnosticMeaningFix
bottomNav-max-5A bottomNav book has more than 5 pagesUse ≤5 pages, or switch to drawer/stack
format-platformA web format (sidebar/tabs) used in storybook.native.ts (or vice-versa)Use mobile formats (drawer/stack/bottomNav) on native, web formats on web
duplicate-keyThe same page key appears twice (incl. across nested books)Make every page key unique
multiple-initialMore than one page sets initial: true in one bookMark exactly one page initial per book
danglingA page has no component, or a book has no childrenGive the page a component / the book at least one page
bad-linklink(x) where x isn't a book()Pass an actual book(...) to link()

My screen/route changes don't show up

Why: navigation is compiled ahead of time — the running app uses the generated navigation.tsx / navigation.native.tsx, not your storybook directly.

Fix: the dev servers already recompile navigation on every storybook change — just keep npm run dev:web or npm run dev:desktop running. If you're compiling manually (e.g. a custom script), re-run after editing a storybook:

npm run build:nav # or: npx @sublime-ui/devkit build:nav --watch

The --watch flag rebuilds automatically on save.

Unable to resolve module ./navigation.js from src/navigation/index.ts

None of these files exist:
* src/navigation/navigation.js(.native.tsx|.tsx|…)
> 2 | export { Navigation } from './navigation.js';

Why: the four navigation files (navigation.native.tsx, navigation.tsx, routes.d.ts, index.ts) are generated, git-ignored build artifacts. On a fresh clone, CI checkout, or a copy that didn't carry ignored files, only your storybooks are present — so the barrel points at files that haven't been generated yet.

Fix: generate them. The dev servers and builds do this automatically (dev:web, dev:desktop, sublime build, build:web, build:desktop), so on a fresh checkout just run your normal command. To generate them directly:

npm run build:nav

This is fixed in current @sublime-ui/devkit, where sublime build always compiles navigation first — upgrade if an older build skipped the step.

Why: build:nav statically analyzes storybook source. It resolves link(settingsBook) when settingsBook is a book(...) defined in the same file; a book imported from another module is not followed (it's reported as a bad-link).

Fix: define linked sub-books in the same storybook file (as local consts), or inline them. (Cross-file imported-book links are a known limitation.)

TypeScript

Cannot find module './tokens.json' / JSON import error

Why: importing tokens.json needs resolveJsonModule.

Fix: ensure your tsconfig.json has:

{ "compilerOptions": { "resolveJsonModule": true } }

Scaffolded apps already set this.

Why: typed navigation is keyed by your route map. useNav() without your AppRoutes type doesn't know your page names/params.

Fix: parameterize the hook with the generated route map, and key params by the route name:

import { useNav } from '@sublime-ui/ui/navigation';
import type { AppRoutes } from '../navigation';

const nav = useNav<AppRoutes>();
const { id } = nav.params<'task'>(); // params for the 'task' route
nav.turnTo('task', { id: 1 }); // params required exactly when declared

An unknown page name or wrong params is a compile-time error — that's the feature working, not a bug.

Desktop

useNative('x') returns null

Why: native services only exist on the desktop (Electron) target. On web and mobile, useNative returns null by design so the same screen runs everywhere.

Fix: guard the call — const greeter = useNative<…>('greeter'); greeter?.hello(). If it's null on desktop too, confirm the service is registered in the main process via registerNative([...]).

build:desktop hangs while packing the installer

Why: the Windows Squirrel installer maker (MakerSquirrel) is slow and can appear to hang on large or unsigned apps while it packs the .exe.

Fix: the default makers no longer include Squirrel — build:desktop produces a portable .zip on Windows/macOS (and .deb/.rpm on Linux), which builds fast and never hangs. If you scaffolded earlier and still have MakerSquirrel in desktop/forge.config.ts, remove it (or keep it knowing the pack step takes several minutes). To intentionally ship a Windows installer, see Packaging → Want a Windows installer?.

Renderer build fails importing @sublime-ui/desktop

Why: the root entry pulls in node/electron and must not enter the renderer bundle.

Fix: import renderer-side code from the renderer-safe subpath:

import { useNative } from '@sublime-ui/desktop/client'; // not '@sublime-ui/desktop'

Mobile (offline Android build)

sublime doctor shows JDK 17 ✗

Fix: on Windows, run sublime setup (installs a portable Temurin JDK 17 into ~/.sublime/ without touching your system Java). On macOS/Linux, install Temurin 17 and set JAVA_HOME.

Build fails on Failed to install … ndk;… / cmake;…

Why: a missing Android SDK component.

Fix: usually auto-healed (the build parses the id, installs it, and retries up to 4 times). If it persists, confirm ANDROID_HOME is set and writable.

Still stuck?