Troubleshooting
Fixes by symptom: no data, SDK cannot reach ApiTraffic, missing bodies, redaction, firewall, APM spans, outbound calls, MCP, API errors and plan limits.
Find your symptom below. Each answer lists the likely causes in the order they usually turn up.
Turn on SDK debug logging first
Most SDK problems explain themselves once debug logging is on. Set the environment variable and restart your app:
API_TRAFFIC_DEBUG=true
Or pass debug: true to the framework call, for example apitraffic.express({ debug: true }). The SDK then logs its activity to the console, including why a send failed and whether it will retry ((will retry) or (permanent, not retrying)). Turn it off again when you are done; it is noisy.
Some problems are logged even without debug: a missing token, and requests dropped because redaction rules could not be loaded.
No data in ApiTraffic
Nothing arrives after installing the SDK
- Restart the process. The token and bucket are read at startup.
- Load your
.envfile. Node does not read it on its own. Start withnode --env-file=.env server.js(Node 20.6 and later), or makerequire('dotenv/config');the first line of your entry file. Without it, the SDK starts with no token and logs thatAPI_TRAFFIC_TOKENis missing. - Check the credentials.
API_TRAFFIC_TOKENmust be an Ingest token andAPI_TRAFFIC_BUCKETthe bucket ID shown on the setup page. A value passed in code (token,bucket) overrides the environment variable. - Check the runtime. SDK 2.x needs Node 20 or later.
- Check the network. See The SDK cannot reach ApiTraffic.
The setup page (Getting Started) shows whether ApiTraffic has heard from your SDK at all: Listening for your application means it has not, SDK connected - waiting for a request means the credentials work but nothing has been captured.
The SDK is connected, but no requests appear
- Middleware order. Register ApiTraffic before your routes. Middleware added after a route never sees its requests.
- The route you called. A health check or static file served before ApiTraffic in the middleware chain is not captured.
- Exclusions. An exclusion rule drops matching requests in the SDK before they are sent. Check Account → Exclusions for a rule that is broader than you meant. See Exclusions.
- Sampling. If you set
requestSampleRate(orAPI_TRAFFIC_REQUEST_SAMPLE_RATE) below1, only that share of requests is sent. Server errors (5xx) are always kept.
Requests appear in the wrong bucket or environment
The bucket comes from API_TRAFFIC_BUCKET (or the bucket option); the environment comes from the ingest token, because each token belongs to one environment. Check the environment menu at the top of the app, then check which token that deployment uses. To send staging traffic separately, create an ingest token in the staging environment. See Environments.
Data stopped arriving after it was working
- Your plan or trial. If capture stopped at a specific time for every service at once, check Plan limits and usage caps.
- A revoked token. If someone revoked the ingest token under Account → API Tokens, ingest refuses it permanently. Create a new one and redeploy.
- A new exclusion. Someone may have added an exclusion that matches your traffic. Exclusions reach running servers without a deploy.
- ApiTraffic itself. Check status.apitraffic.io.
The SDK cannot reach ApiTraffic
Firewalls, proxies and egress rules
The SDK makes outbound HTTPS connections to ingest.apitraffic.io (telemetry) and api.apitraffic.io (settings), plus a realtime connection that pushes setting changes. Allow outbound HTTPS from wherever your app runs: containers, serverless functions and locked-down VPCs often block it by default.
With API_TRAFFIC_DEBUG=true, failed sends are logged with the reason. Timeouts, resets and refused connections are retried briefly from a small in-memory queue, then dropped.
Will my app break if ApiTraffic is down?
No. Capture never blocks your responses or your startup, and the firewall keeps enforcing its last-known policy. The only setting with which an outage can affect your traffic is offlineWafMode: 'closed', which is off unless you turn it on. See If ApiTraffic is unreachable for the full behavior.
Request or response bodies are missing or truncated
The request body is empty
The SDK reads the body your framework parsed. In Express and Koa, register your body parser (express.json(), @koa/bodyparser) before ApiTraffic. A body nobody parsed is not captured, and the firewall cannot inspect it either.
The body shows a placeholder in square brackets
The SDK replaces bodies it cannot or should not send with a short placeholder:
| Placeholder | Why |
|---|---|
[body not captured: N bytes exceeds the M-byte capture limit] |
The body is larger than maxBodyBytes (512 KB by default). It is replaced whole, not cut, so redaction rules never see half a document. Raise the limit with maxBodyBytes or API_TRAFFIC_MAX_BODY_BYTES if you need more. |
…[truncated by ApiTraffic: N bytes total] |
The body was within the limit but grew past it during redaction, so the end was cut. |
[streamed body not captured] |
The body was a stream the SDK could not copy as it was sent, such as a file download. Streams your app writes itself, such as server-sent events, are usually captured from the bytes sent, up to maxBodyBytes. |
[binary body omitted: N bytes, type] |
The content type is not text. |
[body not captured: could not be read] |
The body could not be read or serialized. |
[body not captured: could not be redacted] |
Redaction failed for this body, so it was dropped rather than sent unredacted. |
[body not captured: nested deeper than 256 levels] |
The JSON is nested too deeply to process safely. |
Outbound calls made with fetch have their own cap, maxFetchBodyLength (512 KB by default). See Outbound requests.
The app shows only part of a large body
To keep the page responsive, request details show the first 100 KB of a large body with Show full body to load the rest. The full captured body is stored.
Redaction is not applied
A value I redacted still appears
- Older requests. Rules apply to requests captured after you save them. Requests already stored are not changed.
- Scope. Check that the rule covers the bucket, the environment and the part of the request (header, query, body) where the value appears.
- Proxy and capture traffic. Redact at API rules run inside the SDK. Traffic that reaches ApiTraffic without an SDK, through the proxy or a capture URL, only gets Redact at server rules.
- The SDK has turned default masking off. Credential-shaped keys (
password,token,secretand similar) are masked by default unless the app setsredactSensitiveKeys: falseorAPI_TRAFFIC_REDACT_SENSITIVE_KEYS=false.
See Redactions.
The SDK logged that it dropped requests waiting on redaction rules
The SDK does not send anything until your account’s redaction rules have loaded. If they cannot be loaded at startup, held requests are dropped rather than sent unredacted, and the SDK logs how many. This usually means the app cannot reach api.apitraffic.io; see The SDK cannot reach ApiTraffic.
A redacted value is missing from my workflow
Workflows receive the request as captured, before Redact at server rules run, so those rules never hide a value from a workflow. A value is missing when it was redacted inside your app, by a Redact at API rule or the SDK’s default masking of credential-shaped keys, because it never left your app; or when it’s a credential header such as Authorization, which is always masked. If a workflow needs the value, narrow the Redact at API rule that covers it (a specific scope, key or pattern), or change it to Redact at server so the value reaches the workflow but still isn’t stored. See Redactions.
The firewall blocks legitimate traffic
Stop the blocking now
Pick the fastest option for your situation:
- Switch the policy’s Request Protection to Monitor under Account → Firewall (WAF). It keeps recording what it would block, but blocks nothing. Running servers pick up the change without a deploy.
- Set
API_TRAFFIC_WAF_ENABLED=falseon the affected servers and restart them. This works even when ApiTraffic is unreachable.
Only owners and admins can change firewall policies.
Find out what matched and fix it
Open the blocked request and its WAF tab to see the decision, the policy, and each matched rule with its category, severity and score. Then, in the policy:
- disable the managed rule if it does not apply to your API,
- add a False Positive Exclusion for the route or field that triggers it (for example a rich-text field that looks like HTML), or
- lower the paranoia level or raise the anomaly threshold.
Test the change in Monitor before you go back to Enforcing. See Firewall policies.
Every request is refused with 503
Your servers run with offlineWafMode: 'closed' and could not load a policy at startup, usually because they cannot reach ApiTraffic. Fix the network path, or use the default open mode. See If ApiTraffic is unreachable.
APM spans are missing
Requests have no waterfall
- The start command. APM needs the preload:
node -r @apitraffic/node/register ./server.js. ES-module apps use--importinstead; see Set up APM. - The OpenTelemetry packages. If they are missing, APM is skipped and the console says
otel-peers-missing. - Load order. If your database or cache client is loaded before APM starts, it is never instrumented. The preload exists to avoid this;
register()lists the modules it found already loaded. - Another tracer. With Datadog or New Relic running (
other-apm-detected), or an OpenTelemetry tracer provider already registered (provider-already-active), the bundled setup steps aside. Add the ApiTraffic span processor to your existing setup instead. - Capture settings. Check the APM Capture tab in Bucket Settings. See APM capture settings.
Some operations are missing
The bundled setup instruments a curated set of libraries: pg, mysql, mysql2, mongodb, tedious, oracledb, cassandra-driver, redis, ioredis, memcached, undici (fetch), amqplib, kafkajs and the AWS SDK. Others are opt-in with enabledInstrumentations. A request records up to 500 spans by default (maxSpansPerRequest).
Outbound calls are not captured
No outbound requests appear
- The switch. Outbound capture is on by default. Check that the app does not set
interceptOutbound: falseorAPI_TRAFFIC_INTERCEPT_OUTBOUND=false. - The client. Calls through
http/https(axios, got, node-fetch) and globalfetchare captured. Calls made withundici.request,undici.Clientorundici.Pooldirectly are recorded only as APM spans, without bodies. - The SDK version. Capturing global
fetchneeds SDK 2.x on Node 20 or later.
See Outbound requests.
MCP and OAuth connection problems
My MCP client cannot connect
- Use the server URL
https://api.apitraffic.io/mcp. - Check that your plan includes the MCP server.
- For OAuth, sign in to ApiTraffic in the browser window your client opens, and approve the connection. If the client offers fields for an OAuth client ID and secret, leave them empty.
- For a static token, create it under Account → MCP Tokens (owners and admins) and send it as your client’s configuration describes.
See MCP server.
The agent connects but sees no data, or the wrong data
MCP tokens and OAuth connections are limited to the environment and buckets chosen when they were created or approved. Check the selection under Account → MCP Tokens or Account → Connected Apps. The sample bucket is never visible to MCP connections.
A connection that worked has stopped
An OAuth connection ends when it is disconnected under Account → Connected Apps, when the person who approved it leaves the account or is signed out everywhere (for example after a password change), when its environment is deleted, or after 30 days without use. Reconnect from your client. See Connected apps and OAuth.
The API returns 401, 403 or 429
401 Unauthorized
The token is missing, invalid, revoked or expired. Check the Authorization header and that the token still exists under API Tokens. See Authentication.
403 Forbidden
Read the numeric code in the response body:
| Code | Meaning |
|---|---|
2010 |
Your role, or the token’s role, cannot do this. Creating tokens, generating embed tokens, changing redactions, exclusions, firewall policies, the MFA policy and account settings, and turning on SQL parameter or Redis key capture need an owner or admin (or an Administrator token). Ingest tokens can only send traffic and read SDK settings; use an Administrator or User token for the REST API. To mint embed tokens with the Node SDK, set an Administrator token as API_TRAFFIC_EMBED_TOKEN. |
2221 |
Your plan does not include this feature. data.feature names it. |
2509 |
The call tried to change the read-only sample bucket. |
2510 |
Sample data is turned off for the account. |
2012 |
The account requires multi-factor authentication. |
429 Too Many Requests
Either you exceeded the API’s per-minute rate limit, or a hard-capped plan allowance (such as MCP calls) is used up for this billing period (code 2222). Rate-limit responses carry Retry-After and RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers: wait the number of seconds in Retry-After and retry.
Plan limits and usage caps
Capture stopped and the SDK logs a 429
A hard-capped allowance, such as included requests, is used up for the billing period. Ingest answers 429 with a Retry-After that points to the end of the period, when the counter resets. The SDK honors it and resumes on its own. To resume sooner, upgrade your plan. Plans that bill overage are never blocked. Check Account → Usage.
We email you when an allowance reaches 80% and again at 100%.
Capture stopped and the SDK logs a 402
Your account has no active subscription: the trial ended, or the subscription was cancelled, paused, unpaid or never completed. The response explains which. Choose or fix your plan under Account → Billing; capture resumes shortly after. Your application keeps running either way. See Plan, usage and billing.
I cannot create another bucket or environment
Your plan limits how many you can have. Delete one you no longer use, or upgrade. The sample bucket does not count.
A page shows an upgrade prompt
The feature is not included in your plan. You can still see it fully populated on the sample bucket.
Still stuck?
Choose Ask for help on the setup page, or email [email protected]. Include your bucket ID, the SDK version and the console output with API_TRAFFIC_DEBUG=true, with tokens removed.
Related
-
Quickstart: The install steps, from the start.
-
SDK configuration: Every option and environment variable.
-
If ApiTraffic is unreachable: What the SDK does during an outage.
-
FAQ: Data, performance and compatibility questions.