Skip to main content

Troubleshooting

Organized by symptom area. If your issue isn't here, check the FAQ or open a GitHub issue with backend logs attached.

Installation & Startup

SymptomCauseFix
Backend exits immediately at startupPostgreSQL or Redis not reachableCheck docker ps shows the postgres/redis containers healthy; verify DATABASE_URL/REDIS_URL
Frontend loads but every panel is empty / spinners foreverBackend not reachable through the proxyVerify the backend answers directly (curl http://localhost:8000/health), then check the nginx/ingress proxy config
alembic errors mentioning multiple headsMigration history has parallel branchesRun alembic upgrade heads (plural). miStudio's entrypoint does this automatically; only manual invocations hit it
Jobs stay queued foreverNo Celery worker consuming the queueCheck the worker is running (pgrep -f celery or the worker pod/container); check worker logs for connection errors to Redis
Progress bars never move but jobs finishWebSocket connection blockedSee Real-time updates below

GPU & CUDA

SymptomCauseFix
CUDA not available after an OS updateKernel upgraded; NVIDIA kernel module no longer matches the driverReinstall/rebuild the NVIDIA driver for the new kernel (e.g. dkms autoinstall or rerun the driver installer), then restart Docker/K8s node. This is the single most common "GPU vanished overnight" cause
nvidia-smi works on host but containers see no GPUContainer runtime not GPU-enabledVerify nvidia-container-toolkit is installed and the deployment requests nvidia.com/gpu
GPU memory stays allocated after a job crashesZombie worker process holding VRAMmiStudio's GPU watchdog cleans these up automatically within minutes; to force it, restart the Celery worker
Monitor page shows no GPUsBackend can't see CUDASame fixes as above — the Monitor reflects what PyTorch reports

Out-of-memory (OOM) sizing

Rules of thumb for fitting jobs into VRAM:

  • Model memoryparams × bytes-per-param (FP16: 2 bytes, Q8: 1, Q4: 0.5) plus ~20% overhead
  • SAE training memorybatch_size × d_model × expansion_factor × 4 bytes for activations/gradients, plus the SAE weights twice (weights + optimizer state)
  • Steering needs model + SAE + KV cache simultaneously — the KV cache grows with generation length
SymptomFix
OOM during trainingReduce expansion factor or batch size; train from cached activations so the base model isn't loaded at all
OOM during extractionReduce batch size; use a quantized model; route to a bigger GPU via gpu_id
OOM during steeringUse a smaller SAE width or more aggressive model quantization; shorten max generation length

SAE Training Quality

SymptomCauseFix
>50% dead neuronsSparsity pressure too aggressiveReduce l1_alpha/sparsity_coeff, enable sparsity warmup
Features look polysemantic (messy)Sparsity too lowIncrease the sparsity coefficient (~2×); target L0 of 10–100
Training loss spikesLearning rate too highReduce by 2–5×, increase warmup steps
Training loss plateaus earlyLearning rate too low or not enough stepsIncrease LR or total_steps
JumpReLU produces zero sparsitysparsity_coeff set to an L1-scale valueThese scales are not interchangeable — JumpReLU typical range is 1e-4 to 5e-3. See the framework guide

Key formulas

FrameworkLoss Function
StandardL = MSE(x, x̂) + λ · Σ|z_i| (L1 on activations)
JumpReLUL = MSE(x, x̂) + λ · Σ_i H(z_i - θ_i) (count of active features)
TopKL = MSE(x, x̂) + α · aux_loss(dead_features) (no sparsity penalty — K is structural)

Labeling

SymptomCauseFix
Labels say "uncategorized"LLM couldn't interpret the featureIncrease max examples, try a larger LLM, inspect the activation examples manually
503 errors from labeling jobsThe labeling endpoint has no model loadedLoad a model on your LLM server, or use Fetch Models in Settings to pick one that's actually being served
Labeling timeoutsLocal model too slow for the batch sizeReduce batch size to 1; increase the API timeout
Reasoning model returns empty labelsToken budget consumed by hidden reasoningIncrease max tokens — reasoning models (o-series, gpt-5) spend tokens thinking before answering. miStudio uses max_completion_tokens for these automatically, but the budget still has to be big enough
Labels contain <think>... fragmentsReasoning model with malformed outputmiStudio strips think tags (including unclosed ones) — update to the current release if you still see them

Steering

SymptomCauseFix
Steering has no visible effectStrength too low or feature is weakIncrease strength (try 20–50); verify the feature has a crisp activation pattern in the Feature Browser
Steered output is gibberishStrength too highBack off — there's a sweet spot between "no effect" and "destroyed the model"
Steering job hangs long past expected timeWorker died mid-generationThe zombie-detection watchdog will fail the job; retry it. Check GPU memory wasn't exhausted

Real-time Updates & Progress

miStudio streams all progress over WebSocket, with automatic HTTP-polling fallback.

SymptomCauseFix
Progress frozen but job actually runningWebSocket dropped and fallback hasn't kicked inRefresh the page — the store re-fetches state and re-subscribes
Monitor page metrics staleCelery Beat (the scheduler) not runningCheck the beat process/container — it's separate from the worker
Everything works locally but not behind a reverse proxyProxy not forwarding WebSocket upgradesEnsure the proxy passes Upgrade/Connection headers for the Socket.IO path

Database & Migrations

SymptomCauseFix
Target database is not up to datePending migrationsalembic upgrade heads — with the plural heads, which also handles branched histories
Duplicate-key errors on training metricsPre-2026-07 databases without the unique constraintUpgrade — the migration de-duplicates and adds UNIQUE (training_id, step, layer_idx)
Want to start freshDrop and recreate the database, then restart the backend (migrations run automatically at startup)