> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nimbusbci.com/llms.txt
> Use this file to discover all available pages before exploring further.

# BCI Error Handling

> Handle Nimbus BCI failures with validation checks, confidence thresholds, streaming recovery, and production safeguards.

# Error Handling For BCI Systems

BCI applications should fail predictably. The most important safeguards are input validation, confidence-aware decisions, and clear fallback behavior when signal quality or streaming health degrades.

<Note>
  Python SDK workflows are local and focus on validation, inference, and preprocessing errors. Julia SDK workflows also include API key and core installation errors.
</Note>

## Common Failure Modes

| Category           | Typical Symptom                          | First Check                               |
| ------------------ | ---------------------------------------- | ----------------------------------------- |
| Authentication     | Julia core install or model access fails | API key, network, cached core state       |
| Data shape         | Dimension mismatch                       | Expected feature and trial shape          |
| Invalid values     | NaN, Inf, or unstable predictions        | Preprocessing output and export path      |
| Model mismatch     | Low confidence or feature errors         | Feature count, class count, model family  |
| Poor preprocessing | Near-chance accuracy                     | Frequency band, artifacts, normalization  |
| Streaming drift    | Confidence falls over time               | Session state, electrode quality, fatigue |

## Validate Before Inference

Check the data contract before calling model APIs:

* Features are finite and non-constant.
* Feature count matches metadata and model expectations.
* Labels match trial count and class encoding.
* Test data uses training normalization parameters.
* Streaming chunks match `(n_features, chunk_size)`.

```python theme={null}
import numpy as np

def validate_features(X, expected_features=None):
    if not np.isfinite(X).all():
        raise ValueError("Features contain NaN or Inf")
    if expected_features is not None and X.shape[-1] != expected_features:
        raise ValueError("Feature count mismatch")
```

```julia theme={null}
function validate_chunk(chunk, metadata)
    size(chunk, 1) == metadata.n_features || error("Feature count mismatch")
    all(isfinite, chunk) || error("Chunk contains NaN or Inf")
    return true
end
```

## Confidence Gates

Do not map every prediction directly to an action. Use thresholds that match application risk.

| Confidence | Suggested Action                           |
| ---------- | ------------------------------------------ |
| `>= 0.9`   | Execute low-risk command or accept trial.  |
| `0.7-0.9`  | Ask for confirmation or show alternatives. |
| `0.5-0.7`  | Reject or request a clearer trial.         |
| `< 0.5`    | Stop, recalibrate, or run diagnostics.     |

```python theme={null}
if confidence >= 0.9:
    execute(prediction)
elif confidence >= 0.7:
    request_confirmation(prediction)
else:
    reject_trial("low confidence")
```

## Preprocessing Diagnostics

When confidence is unexpectedly low, check data quality before tuning model hyperparameters.

```julia theme={null}
report = diagnose_preprocessing(bci_data)

if !isempty(report.errors)
    error("Preprocessing failed: $(report.errors)")
end

if report.quality_score < 0.7
    @warn "Low preprocessing quality" score=report.quality_score
end
```

See [Preprocessing Requirements](/inference-configuration/preprocessing-requirements) and [Feature Normalization](/inference-configuration/feature-normalization) for upstream fixes.

## Streaming Recovery

Streaming systems should skip bad chunks, report error rates, and stop when consecutive errors exceed a safe limit.

```julia theme={null}
consecutive_errors = 0
max_errors = 10

for chunk in stream
    try
        validate_chunk(chunk, metadata)
        result = process_chunk(session, chunk)
        consecutive_errors = 0
    catch err
        consecutive_errors += 1
        @warn "Skipping invalid chunk" exception=err

        if consecutive_errors >= max_errors
            error("Stopping stream after repeated chunk failures")
        end
    end
end
```

For chunk sizing and aggregation decisions, see [Streaming Inference Configuration](/inference-configuration/streaming-inference).

## Julia Setup Errors

For Julia SDK deployments:

* Run `NimbusSDK.install_core(api_key)` during setup, not inside a hot inference loop.
* Cache credentials/core installation where appropriate.
* Handle missing or invalid API keys before starting acquisition.
* Keep offline inference assumptions explicit in deployment docs.

```julia theme={null}
using NimbusSDK

if !NimbusSDK.is_core_installed()
    NimbusSDK.install_core(ENV["NIMBUS_API_KEY"])
end
```

## Production Checklist

* Validate every calibration file before training.
* Save model metadata, normalization parameters, and SDK versions.
* Log prediction, confidence, posterior summary, latency, and rejection reason.
* Separate classifier output from command execution.
* Use stricter thresholds for safety-critical actions.
* Monitor session-level confidence trends and rejection rates.
* Provide a fallback path for stream loss, repeated bad chunks, or recalibration needs.

## Troubleshooting Quick Reference

| Issue                          | Likely Cause                        | Fix                                                |
| ------------------------------ | ----------------------------------- | -------------------------------------------------- |
| Accuracy near chance           | Raw EEG or wrong feature band       | Revisit preprocessing and feature extraction.      |
| Confidence always low          | Poor normalization or noisy trial   | Run diagnostics and reuse train normalization.     |
| Dimension mismatch             | Feature count differs from metadata | Check export shape and model metadata.             |
| Works offline, fails streaming | Chunk shape or state handling       | Validate chunks and reset sessions between trials. |
| Cross-session drop             | Electrode/session scale shift       | Use saved normalization params.                    |

## Next Read

<CardGroup cols={2}>
  <Card title="Development Workflow" icon="code" href="/development">
    Project structure and production guardrails.
  </Card>

  <Card title="Streaming Configuration" icon="activity" href="/inference-configuration/streaming-inference">
    Chunking, aggregation, and quality gates.
  </Card>

  <Card title="Preprocessing Requirements" icon="list-filter" href="/inference-configuration/preprocessing-requirements">
    Prevent data-quality failures upstream.
  </Card>

  <Card title="Basic Examples" icon="play" href="/examples/basic-examples">
    Compact recipes for common workflows.
  </Card>
</CardGroup>
