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

# Troubleshooting

> Common issues and how to diagnose them.

## I don't see any traces in the dashboard

Walk this list top to bottom — the first match is almost always the cause.

<AccordionGroup>
  <Accordion title="Did you call instrumentServer before registerTool?" icon="arrow-up-9-1">
    Tools registered before instrumentation are not patched. Move
    `instrumentServer(...)` to immediately after `new McpServer(...)`.
  </Accordion>

  <Accordion title="Is samplingRate accidentally 0?" icon="filter">
    `samplingRate: 0` drops everything. Default is `1.0`. Print it on startup:

    ```ts theme={null}
    console.log('samplingRate =', telemetryConfig.samplingRate ?? 1.0)
    ```
  </Accordion>

  <Accordion title="Is enableTracing turned off?" icon="toggle-off">
    `enableTracing: false` disables the exporter entirely. Default is `true`.
  </Accordion>

  <Accordion title="Is the exporterEndpoint right?" icon="signal-stream">
    Should look like `https://otel.sedata-ai.tech/v1`. The package appends
    `/traces` and `/metrics`. A trailing slash is fine. A path like
    `/v1/traces` would result in `/v1/traces/traces` — wrong.
  </Accordion>

  <Accordion title="Is the auth header set?" icon="key">
    Switch to console exporter and confirm spans are produced at all:

    ```ts theme={null}
    exporterType: 'console'
    ```

    If they print, the issue is auth or endpoint. If they don't print, the
    issue is upstream of export (instrumentation or sampler).
  </Accordion>

  <Accordion title="Is there more than one @opentelemetry/api in node_modules?" icon="boxes-stacked">
    Run `npm ls @opentelemetry/api`. Multiple versions create no-op tracers.
    Dedupe with `npm dedupe` or pin a single version.
  </Accordion>

  <Accordion title="Does the process exit before flushing?" icon="power-off">
    Short-lived scripts can exit before the batch processor flushes. Always
    `await telemetry.shutdown()` before `process.exit`.
  </Accordion>
</AccordionGroup>

## I see traces but metrics are missing

<AccordionGroup>
  <Accordion title="Are you using exporterType: 'console'?" icon="terminal">
    The console exporter has **no metric reader** — by design, for
    local debugging. Switch to `otlp-http` to get metrics.
  </Accordion>

  <Accordion title="Is enableMetrics: false?" icon="toggle-off">
    Default is `true`. If your config object came from another module, double
    check it isn't being overridden.
  </Accordion>

  <Accordion title="Is metricExportIntervalMs too high?" icon="clock">
    Default is `5000` ms. If you set `60000`, you'll wait a minute between
    flushes. For local dev, try `2000`.
  </Accordion>

  <Accordion title="Did you await shutdown() at exit?" icon="hourglass-half">
    Without it, the last batch — including `mcp.server.session.duration` —
    is dropped.
  </Accordion>
</AccordionGroup>

## Safety checks are always failing

```text theme={null}
console.warn: Safety check API call failed, allowing execution
```

<AccordionGroup>
  <Accordion title="Is the API key set?" icon="key">
    The wrapper uses the key passed to `instrumentServer` via
    `exporterAuth.token` or `exporterAuth.apiKey`. Confirm it's loaded:

    ```ts theme={null}
    console.log('SEDATA_TOKEN set:', !!process.env.SEDATA_TOKEN)
    ```
  </Accordion>

  <Accordion title="Is the parameter actually a string?" icon="quote-left">
    The wrapper only checks string values. Numbers, objects, and `undefined`
    pass through untouched and no safety attributes are recorded.
  </Accordion>

  <Accordion title="Is the parameter name correct?" icon="key">
    `parameterName` must match a field on your `inputSchema`. Typos result in
    silent skips.
  </Accordion>

  <Accordion title="Is the network reachable?" icon="wifi">
    Try `curl https://api.sedata-ai.tech/security/safety-check` — if it
    can't reach, neither can the SDK.
  </Accordion>
</AccordionGroup>

## My handler runs even when content is flagged

The wrapper short-circuits on flagged content — it does **not** call your
handler. If your handler runs anyway, one of these is true:

* The wrapper isn't actually applied (you registered the raw handler).
* The safety API failed (logged warning) and the wrapper fail-opened.
* The parameter wasn't a string and was skipped.

Confirm by inspecting the span: a `mcp.safety_check.flagged === true`
attribute means the wrapper ran. If you see it AND your handler ran, file an
issue with the trace id.

## The error spam in dev is annoying

The wrapper prints debug logs by default (e.g.
`Safety check wrapper called with params: ...`). These are deliberate while
the package is at 0.x. To silence:

```ts theme={null}
const origLog = console.log
console.log = (...args) => {
  if (typeof args[0] === 'string' && args[0].startsWith('Safety check')) return
  if (typeof args[0] === 'string' && args[0].startsWith('Instrumentation params')) return
  if (typeof args[0] === 'string' && args[0].startsWith('Has _safetyCheck')) return
  origLog.apply(console, args)
}
```

Track [#logging](https://github.com/sedata-ai/sedata-ai-packages) for a proper
log-level option.

## TypeScript: type 'any' on tool params

The `safetyCheck` wrapper currently types its handler as `(params: any) =>
any`. To get proper typing, annotate the inner function:

```ts theme={null}
safetyCheck(
  async ({ text }: { text: string }) => { /* ... */ },
  { parameterName: 'text' },
)
```

## Still stuck?

<CardGroup cols={2}>
  <Card title="FAQ" icon="circle-question" href="/faq">
    Quick answers to common questions.
  </Card>

  <Card title="Support" icon="life-ring" href="/support">
    How to reach the team.
  </Card>
</CardGroup>
