Troubleshooting¶
Known startup and acquisition failures, what actually causes each one, and what the toolbox does about it today. These are real failures the project hit and fixed (or mitigated) — not a generic "things that could go wrong" list — so each entry says what you'll actually see.
Install and launch¶
The app asks "Set up this deployment?" on first launch¶
What you'll see: the very first time you open the app on a machine, a dialog appears — "This machine has no site profile…" — with three buttons: "Use generic (this machine has no lab/course)", "Set up a profile…", and "Not now".
This is not an error. It's a one-time question: this machine has no site profile (config/site.local.json) yet, and the app is asking once whether it should have one, rather than silently guessing. For a personal machine, a student laptop, or working through Getting started, click "Use generic…" — that's correct, and it writes a generic profile so the prompt won't reappear. For an actual lab or classroom deployment, "Set up a profile…" opens the full form (institution, push destination, approved operators, and the rest — see Site profile for what each field does).
Clicking "Not now" writes nothing, so the prompt comes back at the next launch rather than settling into some in-between state — if you keep seeing it, that's why; pick one of the other two buttons to make it stop.
The desktop icon shows a splash, then closes, with no error¶
What you'll see: double-clicking the Desktop shortcut briefly shows the splash screen, then the window disappears. No error dialog, no console — because the shortcut launches a console-less process (pythonw.exe), which cannot print anything at you even if it wanted to.
Where to look first:
The toolbox installs a crash handler at startup (sys.excepthook plus a thread-exception hook) that writes every unhandled exception here, with a header recording the launch environment (CONDA_PREFIX, whether the env's native library directory is on PATH, whether the install is editable). Read that first — it names the actual exception, not just "it closed".
If the log itself says something — a missing package, an import error, a schema/path problem — that is the real failure; fix whatever it names.
Reproduce with a console, to see the same failure interactively instead of reading it after the fact: run the console-script alias of the same app from a plain, non-activated shell (not one where you've run conda activate):
If that works but the icon doesn't, the difference is specific to the shortcut (see the next entry, and check the shortcut's working directory). If both fail, don't expect the console to show a traceback by itself — the next entry's failure mode terminates in native code with no Python exception, so a console alone doesn't reveal it; use the exit-code check there.
There is no log at all — not empty, absent¶
What you'll see: the same splash-then-close, but this time %LOCALAPPDATA%\ssvep-toolbox\startup-error.log — and even its parent ssvep-toolbox folder — does not exist. The crash-logging machinery above never ran.
What this means: the process died in native code, before any Python exception handler could run. Check the exit code to confirm:
0xC06D007F (ERROR_DELAY_LOAD_FAILED) is the signature of this failure. It is almost always MKL — numpy/scipy's compute backend — failing a delay-load: MKL loads its actual compute kernels lazily, at the first linear-algebra call, not at import numpy. That's why the app gets far enough to paint its splash (which only needs Qt) before vanishing the moment startup touches numpy. A structured exception like this terminates the process before Python's own exception handling ever runs, which is why the crash log stays empty rather than catching it.
Why it happens: the native libraries MKL needs live in the conda environment's Library\bin, and normally only conda activate puts that directory on PATH. A desktop shortcut launched by Explorer never runs conda activate — so a shortcut is exactly the situation where this bites, and a plain activated-shell launch usually is not.
What the toolbox does about it: import ssvep now repairs PATH in-process, before any numeric code runs, so this should not happen regardless of how the app was launched. If you still see it: confirm the environment actually has a Library\bin directory (a broken or partial env install can be missing it), and confirm the shortcut is pointed at the environment you think it is — a stale shortcut from before a conda env remove/recreate will point at a path that no longer has what it needs.
Install/launch fails, or crashes on first real computation, after pip install¶
If you ran pip install -e . without --no-deps (or added packages with plain pip install afterward), pip may have re-resolved and overwritten some of the conda-built dependencies with PyPI builds of the same package — most consequentially numpy's BLAS backend. The import can still succeed; the crash shows up the moment something does real linear algebra, which can look identical to the MKL delay-load failure above but for a different underlying reason. Fix: deactivate first (conda deactivate — conda refuses to remove the environment you're currently in), then recreate it (conda env remove -n ssvep, then conda env create -f environment.yml), reactivate (conda activate ssvep), and reinstall with pip install -e . --no-deps. See Installation for why the flag matters.
pytest (or the app) imports ssvep from a different checkout than you expect¶
pip install -e . records an absolute path to the checkout it was run in, and the environment always imports ssvep from whichever checkout ran that command most recently — reinstalling from a second clone does update it, no need to uninstall the first. The confusing case is the opposite: you move, rename, or delete the checkout that install still points to (or switch to working in an older second clone) without re-running pip install -e . --no-deps from the checkout you actually mean to use — the environment keeps importing from the old path regardless of which folder your terminal is sitting in. If behaviour doesn't match the code you're looking at, first confirm which tree is really being imported (python -c "import ssvep; print(ssvep.__file__)" from the activated env), and reinstall from the checkout you intend to use if it's wrong.
Acquisition¶
After finishing the impedance check, starting the run is refused for several seconds¶
What you'll see: you run the impedance/QA check, click Done, prepare the run (Start selected run), then click Start recording on the live-EEG pane — and for a few seconds that's disabled, or refuses, reporting that impedance is still running, even though you already stopped it.
What this means: this is expected on real hardware, not a bug to work around. Releasing the amplifier from the impedance-measurement (lead-off) mode is a real, multi-step handoff — on the OpenBCI Cyton it's several sequential serial round-trips plus a session release, which has been observed to take five to ten seconds. The check now reports that state honestly: the status line reads "stopping… (releasing the amplifier — this can take several seconds)", and the run genuinely cannot start until the amplifier has actually finished releasing — showing "ready" earlier than that would be reporting a state that isn't true yet.
What to do: wait. It resolves itself once the amplifier finishes releasing; there is nothing to retry or reconfigure. This does not occur on the synthetic test board — there's no real amplifier to hand off, so nothing to measure or release (see Getting started).
If none of this matches what you're seeing¶
The startup-error log (above) is the first thing to capture — most launch failures leave a trace there even when the on-screen symptom looks identical to something else. Beyond that, this project's issue tracker is where failures like these get diagnosed and fixed — every entry above started as a bug report there, filed with exactly this kind of detail: what you did, what you expected, and what you saw instead.