Skip to content
CADCAMFUN
Docs

Documentation

Desktop troubleshooting

Identify the failing process, inspect the real endpoint and data directory, and recover without confusing preview with persistence.

Identify the runtime before changing it

A desktop session has separate failure boundaries: Vite supplies frontend assets during development; the Tauri Rust process owns native integration; the Bun sidecar serves application requests and persistence; the SolidJS webview connects to that API. A blank window, a boot timeout, a 401 response, and an empty project list can have different causes.

Launch modeBackendWhat it can establish
Desktop package dev with no sidecar URLIn-memory fake clientSupported fixture-based screen behavior, not durable application storage.
Vite with URL and tokenSelected running sidecarBrowser-to-server requests and persistence in that server's directory.
Root desktop:devCompiled supervised sidecarNative shell, webview, bundled server/resources, and application flow.
Desktop tauri:dev with no existing binaryGenerated stub sidecarIsolated shell behavior; the stub is not the full application API.

Record the launch command and whether the endpoint came from Tauri or Vite variables. Do not delete a database or reinstall dependencies merely because a different runtime shows different data.

Understand startup timing

The Rust shell generates a launch token, resolves application data and migration directories, and spawns the target sidecar. The child binds 127.0.0.1 on an ephemeral port. It waits until its public /api/health answers, then writes a JSON ready event with that port. The webview invokes get_sidecar_endpoint and creates its managed API runtime.

BudgetCurrent valueMeaning
Shell ready handshake60 seconds per startMaximum wait for the child's usable ready event.
Automatic supervisor restartOneA failed child is not restarted indefinitely.
Native endpoint wait125 secondsTwo ready budgets plus slack.
Webview connection attempt30 secondsHealth/connection timeout for an attempt.
Webview retry loop150 seconds, 750 ms pausesRe-resolves endpoints before offering a timed-out failure.

Retry restarts webview connection attempts; it does not replenish an exhausted Rust supervision budget. Fix the startup cause and relaunch the app when the supervisor has reached its terminal failed state. A port from before a child restart can be stale.

Check ports and health separately

Vite uses localhost:1420 with strict port selection, matching Tauri's configured development URL. It fails instead of silently moving to another port. The sidecar port is unrelated and changes between launches. The companion HTTPS port is a third listener, default 8443, and Studio uses loopback 4396.

Probe an isolated development sidecar; replace the example port/token
CADCAM_URL=http://127.0.0.1:43111
CADCAM_TOKEN=local-development-token

curl --max-time 5 --fail-with-body "$CADCAM_URL/api/health"
curl --max-time 5 --fail-with-body "$CADCAM_URL/health"   -H "Authorization: Bearer $CADCAM_TOKEN"
curl --max-time 5 --fail-with-body "$CADCAM_URL/version"   -H "Authorization: Bearer $CADCAM_TOKEN"

The public health route returns status and timestamp. Authenticated system routes expose readiness and the application version. A healthy process does not prove all providers, database queries, or native dialogs work. Compare the Health API and System API when selecting probes.

If port 1420 is occupied, identify and stop the existing development server deliberately. If a remembered API port refuses connections, read the current ready event or re-resolve the Tauri endpoint rather than guessing neighboring ports.

Reproduce with an isolated sidecar

A source process is useful for separating native-bundle issues from server behavior. Run this from the repository root in an interactive terminal; it creates a fresh data directory and uses the generated migration folder explicitly.

Keep this terminal and stdin open
CADCAM_DIAGNOSTIC_DIR=$(mktemp -d /tmp/cadcamfun-desktop-guide.XXXXXX)
CADCAMFUN_TOKEN=local-development-token CADCAMFUN_DATA_DIR="$CADCAM_DIAGNOSTIC_DIR/data" CADCAMFUN_MIGRATIONS_DIR="$PWD/packages/db/drizzle" CADCAMFUN_AI_OFFLINE=true bun --no-env-file apps/sidecar/src/main.ts

Copy the announced port into the probe variables in a second terminal. Offline AI mode avoids depending on a configured remote model for basic startup diagnostics; it does not run an alternative local model. The server observes stdin EOF, an explicit shutdown event, and normal runtime interrupts.

A source process uses current files. A native process uses the compiled executable already staged under src-tauri/binaries. If only the compiled run fails, rebuild through bun run build:sidecar and inspect bundling/migration resources. Editing TypeScript does not replace an already running executable.

Resolve the actual database path

Process/toolPath selection
Tauri-launched sidecarTauri app_data_dir(), then cadcamfun.db.
Manual sidecarCADCAMFUN_DATA_DIR/cadcamfun.db.
Migration CLIDATABASE_URL, otherwise ./data/cadcamfun.db relative to its process directory.
Root db:migrate wrapperRuns in the database package, normally giving packages/db/data/cadcamfun.db by default.
Local Studio APICADCAMFUN_DB, then DATABASE_URL, then repository-root data/cadcamfun.db.

These files are not aliases. Match the selected process path before investigating missing drawings. Browser fixtures never open these SQLite files. The sidecar applies migrations only when its configuration supplies a migration folder; omitting it does not automatically discover the source-tree folder.

The database layer enables WAL and foreign keys. Before an existing database upgrade it writes an automatic pre-migration backup and retains five matching backups. It does not create such a backup on every save, unchanged startup, first creation, or in-memory test. Preserve a consistent backup through the database/recovery procedure; copying only the main file of a running WAL database can omit committed WAL content.

Read protocol output and logs

In a source sidecar terminal, stdout is reserved for ready/error protocol events and JSON application logs go to stderr. In the native app, the Rust logging plugin captures shell-side events, including supervised child output. The shell redacts lines that may contain its launch credentials.

The native get_logs_dir command resolves the operating-system application log directory. It is more reliable than assuming one universal path across systems. A developer diagnostic inside the webview can invoke it through the existing Tauri command interface; native path opening is constrained to permitted folders and refuses executable file types.

The reusable boot-screen component supports an optional View logs callback, but the current App.tsx does not pass that callback. Do not assume a View logs button will be visible during a startup failure. Keep the development launching terminal available or use the native log directory through an appropriate diagnostic surface.

For a report, include the launch mode, non-secret data/migration paths, elapsed wait, current API version, exact error tag/message, and last relevant startup events. Redact launch/session/device tokens, pairing links, model keys, and signing material.

Distinguish authentication from empty data

The browser real-client mode requires both VITE_SIDECAR_URL and VITE_SIDECAR_TOKEN. A URL without a token does not activate the fake fallback; endpoint resolution fails. Variables must be supplied before Vite starts. Updating a parent shell does not reconfigure a server already running.

Browser connected to the isolated source process
VITE_SIDECAR_URL=http://127.0.0.1:43111 VITE_SIDECAR_TOKEN=local-development-token bun run --filter @cadcamfun/desktop dev

Protected calls can use account session context in addition to the application token. Companion and standalone bridge tokens have narrower scopes and are not substitutes for a launch token. A 401 needs credential diagnosis; a 403 needs operation/access diagnosis; an absent or inaccessible project can be reported as 404.

Some screens, including project child-resource tabs, currently turn individual list errors into empty arrays. A blank tab is not sufficient evidence that records were deleted. Read the corresponding project, drawing, or toolpath endpoint before recreating work.

A valid launch token is 64 hexadecimal characters (32 random bytes) and changes on every launch. A token of a different shape was not issued by the desktop shell.

Recognize preview and native limitations

The fake API handles selected projects, drawings, materials, tools, machines, toolpaths, KV, and generator paths. Unsupported collections return HTTP 501 with a preview-specific message. Fixture data belongs to the running page. A successful preview action cannot demonstrate persisted organization, plugin, billing, or live provider behavior.

Native dialogs, keychain operations, tray, updater, and macOS materials require the Tauri host and the correct capabilities. A registered command can still be unavailable to the webview under its capability configuration. For file opening, the shell registers supported associations and forwards paths; that alone does not prove a particular editor imported the contents.

Graphics failures are another boundary. A non-zero container size, visible entities/layers, unlocked selection, and supported WebGL are prerequisites for the relevant viewport interactions. A rendered mesh is evidence of rendering, not a successful save or CAM verification. Use the viewport diagnostics for worker capacity, timeout, and four-view behavior.

Recover preference and display issues

The shared webview preference record is cadcamfun.settings. Defaults include millimetres, system theme, three decimals, GRBL preference, snap enabled, tolerance 0.01 mm, and glass enabled. Stored fields are validated independently; invalid values fall back without making the shell fail. Full/blocked local storage can prevent persistence.

Changing display units does not rescale the stored CAD geometry. Document tolerance is propagated through the shared CAD/generator/verification settings helper. Some feature/rotary values explicitly use degrees; drawing angles use radians. Verify the field contract before diagnosing a numerical mismatch as corrupt geometry.

Glass behavior depends on Tauri/macOS support. The implementation uses Liquid Glass where supported, vibrancy on older macOS through the plugin, and an opaque fallback when unavailable or disabled. Theme/material changes do not alter geometry, project ownership, or machining evidence.

Prefer the relevant settings or feature control over clearing all webview storage. That storage can also contain session/editor handoffs. A visual preference reset is not a database repair procedure.

Separate UI recovery from machining evidence

A loaded project, successful HTTP save, animated toolpath, and generated NC are different observations. Before relying on a saved machining result, inspect the exact NC, source drawing/stock, tool assemblies, machine envelope, selected post, and verification release/issues for that result.

The CAM snapshot code preserves kernel evidence only when the current NC text and its hash match. Portable program writes validate document consistency and may re-evaluate captured kernel requests. Editing NC or changing stock can invalidate previous evidence. Reopening plain NC can parse a program without restoring the same manufacturing proof.

After a crash or interrupted save, first inspect the saved row and its versions. The CAM save modal records the previous program before an update, while toolpath detail manual save records the updated revision. Project history is separate again. Use the history comparison to choose a recovery path.

Do not convert an unresolved check into an accepted operation because the UI recovered. Re-run the appropriate verification against the actual resources and NC; an application health probe has no authority over machine safety.

Triage one failure at a time

  1. Record launch mode, process versions, ports, and actual data directory.
  2. Probe health, then one protected read. Separate connectivity from authorization.
  3. Inspect structured startup/migration errors before resetting or deleting anything.
  4. Reproduce against an isolated source process when a compiled/native issue is suspected.
  5. Fix the identified cause, restart the appropriate process, and update stale endpoint variables.
  6. Reopen the saved document/program and inspect persisted state, versions, exports, and current verification.

Implementation anchors are app/App.tsx, app/sidecar.ts, src-tauri/src/{sidecar,commands,lib}.rs, sidecar main.ts/config.ts/shutdown.ts, and the database lifecycle. Local development supplies configuration details; companion pairing handles its separate network boundary.

Startup checklist

  1. Is the sidecar binary present for this platform (src-tauri/binaries/sidecar-<target triple>)? desktop:dev builds it; tauri:dev may use a stub.
  2. Are migrations staged in src-tauri/resources/migrations? bun run build:sidecar or bun scripts/build.ts --only=resources restages them.
  3. Did the sidecar print ready within 60 seconds? Look for an error line on stdout and JSON logs on stderr in the log directory (get_logs_dir).
  4. Did it restart? Only one automatic restart is allowed; a second failure leaves the status at failed.
  5. Does GET /api/health answer on the reported port? If it does but protected routes return 401, the token belongs to a different launch.
  6. Is the data directory writable and is the database file not held open by another process with incompatible migrations?
TimerValueOwner
Ready handshake60 s per attemptRust supervisor
Automatic restarts1Rust supervisor
Endpoint wait125 s (two handshakes + 5 s)get_sidecar_endpoint
Webview recovery budget150 s, 30 s per attempt, 750 ms between attemptsWebview
Shutdown grace2 s after the shutdown line, then the process is reaped (up to 5 s)Rust supervisor

Reading the logs

Sidecar logs are JSON lines on stderr, kept separate from the stdout handshake. Lines that could contain credentials are replaced by [redacted: line may contain credentials] before they are written, so a redacted line in a log is expected, not corruption. If the handshake itself carried such a line, the reported startup error is the redaction marker; read the surrounding stderr lines for context.

The log directory is platform-specific. Get it from the get_logs_dir command rather than guessing a path, and open it with open_path, which accepts the application log directory.

Error messages and what they mean

MessageWhere it comes fromWhat to do
The 3D mesh queue is full. Reduce the scene complexity.Viewport meshing queue (128 jobs)Hide or simplify bodies; the queue was cleared
3D meshing timed out. Reduce the scene complexity.One meshing job exceeded 15 sSimplify the solid; the worker was restarted
No AI provider is configured. Add an API key in the AI settings.Assistant stream, code: "config"Add a provider key; nothing else is wrong
Legacy migration journal does not match local migrationsDatabase upgrade at startupKeep the data directory; install the matching version
Pull request is not openMerging or closing a merged/closed PRRefresh the PR list
Unknown revision <rev>History restore or log with a bad revisionPick a revision from the log
Plugin <id> may not use "<capability>": it was not granted at install timePlugin contextReinstall and grant the capability, or change the plugin
The machine's rotary axes cannot reach this work plane within their limitsIndexed machiningUse another setup for that face

In 3D

Where desktop failures happen Drag to orbit · scroll to zoom · right-drag to pan
Processes at run time. The Tauri shell spawns the sidecar and waits for its {”event”:”ready”,”port”:N} line on stdout (sidecar.rs); the webview then talks HTTP to 127.0.0.1 on that port with the bearer token. The sidecar owns the SQLite database, the embedded nikcli AI host (CADCAMFUN_AI_HOST=nikcli, the default) and plugins; the mobile app reaches it through companion pairing.