Debug Common Issues
Quick fixes for frequently encountered problems.
Build Errors
Linter issues (oxlint)
Symptom: Unexpected lint errors or warnings when running pnpm lint.
Cause: The project uses oxlint (not ESLint) for TypeScript linting. oxlint is faster but has a different rule set and configuration model.
Fix:
Common quick checks:
- Confirm you are running
pnpm lintfrom the repo root (not a subdirectory) - Confirm
node_modulesis populated (pnpm install) - Use
/* oxlint-disable */comments (noteslint-disable) for lint suppression - Run
./tools/precheck.sh --fixto auto-fix formatting and linting issues
Clippy idiom errors
Symptom: cargo clippy or the pre-commit hook reports clippy warnings that are not obvious from the code (e.g.,
clone_on_copy, needless_pass_by_ref_mut, large_enum_variant).
Fix: See docs/solutions/build-errors/rust-clippy-idioms-catalog.md for a catalog of common patterns and their
fixes.
The pre-commit hook runs gitleaks only. For clippy and other lint checks, run the quality gate:
./tools/precheck.sh # scoped to changed files vs main (check only)./tools/precheck.sh --fix # auto-fix formatting/linting, then check./tools/precheck.sh --no-test # skip cargo testA common false positive: #[tool_handler] or #[derive(FromRequest)] macros generate runtime dispatch code invisible
to clippy, which then reports dead_code on the variants they dispatch. Use a targeted #[allow(dead_code)] with a
comment naming the macro. See docs/solutions/build-errors/proc-macro-dead-code-false-positives.md.
TypeScript type errors after Rust struct changes
Symptom: TypeScript fails with “cannot find name” or type mismatch errors on types from
packages/contracts/generated/.
Cause: The generated bindings are stale. They are produced by Specta from Rust structs via #[specta::specta]
annotations.
Fix:
pnpm generate:typesRun this any time you add, remove, or rename a field on a Rust type that has #[derive(specta::Type)]. The output goes
to packages/contracts/generated/bindings.ts — do not edit this file by hand.
Note on casing: Specta preserves Rust snake_case field names in TypeScript output. storage_path generates as
storage_path, not storagePath. Don’t assume camelCase conversion.
Runtime Errors
”Database version is newer than app version”
Symptom: The app shows an error about the workspace database version being ahead of the app.
Cause: The workspace was created by a newer build (e.g., switching branches after running migrations).
Fix: Reset dev data:
./tools/dev/reset-app-data.sh # interactive./tools/dev/reset-app-data.sh --force # skip confirmationThis clears .data/ (dev workspaces and settings). Production data at ~/Inklings/ is never touched.
MCP server won’t start
Symptom: MCP status shows “not running” despite being enabled in settings.
Common causes:
-
Port conflict: Something else is already on port 7862:
Terminal window lsof -i :7862Change the MCP port in app settings, or kill the conflicting process.
-
No workspace open: The MCP server starts only when a workspace is open. Open a workspace first.
-
Feature not enabled: Confirm
mcp_enabledistruein settings (Settings → Developer → MCP Server).
Test Failures
Integration test isolation
Symptom: An integration test passes alone but fails when run alongside others. Or: a test passes on the first run but fails on subsequent runs without code changes.
Cause: SQLite integration tests (tests/core/) use TempDir for isolation, but if a test panics before cleanup,
the temp directory may persist.
Fix: Each TestWorkspace::new() call creates a fresh temporary directory. Tests that share a TestWorkspace must
not rely on execution order. If a test is modifying shared state, verify it uses its own TestWorkspace instance.
For FK constraint failures: verify that pages referenced as parents exist before calling create_batch. Filter orphan
parent_slug values in fixture data.
Playwright setup: “browser not installed”
Symptom: Playwright tests fail immediately with a message about the browser binary not being found.
Fix:
cd apps/desktop/testspnpm exec playwright installOr for E2E:
cd tests/e2epnpm exec playwright installPlaywright browsers are not installed by pnpm install — they require a separate step.
Playwright test timing out
Symptom: A test passes locally but times out in CI, or passes intermittently.
Checks:
-
Increase the timeout for the specific assertion:
await expect(element).toBeVisible({ timeout: 10000 }); -
Use
waitForAppReady(page)before any assertions — it waits for the sidebar to be visible, which confirms the app has loaded. -
For E2E tests: CI runs with
workers: 1(sequential). If a test assumes a specific page ordering that varies with parallel execution, it may fail only in CI.
Selector not found in Playwright tests
Symptom: Playwright cannot locate an element that is visible in the running app.
Approach:
-
Run in headed mode to see the actual DOM:
Terminal window pnpm --dir apps/desktop/tests test:headed -
Use Playwright UI mode to interactively explore elements:
Terminal window pnpm --dir apps/desktop/tests test:ui -
Prefer role-based selectors (
getByRole,getByText) overdata-testidattributes. Role-based selectors are more resilient to DOM restructuring. -
For E2E: check
tests/e2e/seed.spec.tsto understand what theappPagefixture sets up before your test runs.
Development Environment
Dev data reset
Clear all app state for the current development environment (workspaces, settings):
./tools/dev/reset-app-data.sh # interactive, asks for confirmation./tools/dev/reset-app-data.sh --force # no confirmationThis only clears .data/ (the dev environment directory). It never touches:
~/Inklings/(production workspaces)~/Library/Application Support/Inklings/(production settings)
After resetting, the app treats the next launch as a first run and shows the onboarding tour.
Type generation issues
If pnpm generate:types fails or produces unexpected output:
-
Build error in
src-tauri: Fix any Rust compile errors first — type generation compiles the Tauri app. -
Stale generated file: Delete
packages/contracts/generated/bindings.tsand re-runpnpm generate:types. -
Changed struct fields: After adding fields to a Rust type that derives
specta::Type, runpnpm generate:typesand commit the updatedbindings.ts. The TypeScript frontend will immediately see the new fields. -
Missing
#[specta::specta]on a new command: If a new Tauri command is missing the#[specta::specta]attribute, it will not appear inbindings.ts. Add the attribute and re-run type generation.
Pre-commit hook failures
Symptom: git commit is rejected by the pre-commit hook.
The pre-commit hook runs gitleaks only (secret scanning). Formatting and linting are not enforced at commit time.
Common fixes:
- gitleaks failure: A staged file contains a string that looks like a secret. Review the flagged file. If it is a
false positive, use
gitleaks --baseline-pathor add an allowlist entry.
For formatting and linting issues, run the quality gate before committing:
./tools/precheck.sh --fix # auto-fix formatting/linting, then validateSee Also
- Full solution docs:
docs/solutions/ - Build errors specifically:
docs/solutions/build-errors/ - Database patterns:
docs/solutions/database-issues/ - Architecture decisions:
docs/ADR/
Was this page helpful?
Thanks for your feedback!