Use this page when you know the symptom but not which product layer caused it. Start at the top of the request path and change one variable at a time.
producer
→ GraphJSON API
→ collection storage
→ query or visualizer
→ dashboard, alert, export, or embed
A problem at an earlier layer affects everything after it. An embed cannot display an event that never arrived, and an alert cannot evaluate a chart that returns too little history.
Fast symptom index#
| Symptom | Start here |
|---|---|
| Logging request fails | Ingestion requests |
| Request succeeds but event is absent | Accepted event is missing |
| Samples has data but a chart is empty | Empty or incorrect visualization |
| SQL fails, times out, or returns surprising data | SQL queries |
| Dashboard tile is broken or stale | Dashboards |
| Iframe is blank, wrong, or exposes too much | Embeds |
| Alert did not evaluate or notify | Alerts |
| Segment, Stripe, or Vercel data stopped | Integrations |
| Cannot sign in, reset a password, or complete 2FA | Account access |
| Subscription or invoice looks wrong | Billing |
| Several unrelated surfaces fail together | Possible service incident |
Record the boundary first#
Before changing anything, record:
workspace:
environment:
surface or endpoint:
collection:
approximate time:
time zone:
HTTP status or visible error:
one request, one producer, or everyone:
last known working time:
recent deployment or configuration change:
Do not record an API key, password, session token, complete private payload, full generated embed URL, or payment-card data.
Ingestion requests#
Read the status before parsing the body:
const response = await fetch("https://api.graphjson.com/api/log", options);
const text = await response.text();
console.log({
status: response.status,
body: text.slice(0, 300)
});
| Result | Meaning | Next action |
|---|---|---|
2xx |
Request accepted | Search the correct workspace, collection, and event time |
400 |
Key, method, JSON, timestamp, query, or field is invalid | Fix the request; do not retry unchanged |
429 |
Ingestion request guardrail exceeded | Back off with jitter and reduce concurrency |
500 |
Ingestion failed internally | Retry a bounded number of times |
| Timeout or network error | Outcome may be unknown | Retry only with a stable event_id and deduplicate later |
Validate the logging envelope separately from the event:
{
"api_key": "redacted",
"collection": "product_events",
"timestamp": 1785081600,
"json": "{\"event\":\"signup_completed\",\"event_id\":\"evt_01J...\"}"
}
The outer body is JSON and json is a serialized JSON object. Timestamps are whole Unix seconds, not milliseconds.
For exact error handling and limits, use Errors and limits.
Accepted event is missing#
If logging returned 2xx:
- confirm the API key belongs to the intended workspace
- confirm the request’s exact collection
- open
all_eventsand use Samples - set a broad range such as 7 days ago → now
- remove every filter
- order descending
- convert the request timestamp to an ISO time
- check collection retention
- search by a stable
event_id
console.log(new Date(timestamp * 1000).toISOString());
An event can be accepted but appear outside the expected day because its source timestamp or analysis time zone is wrong.
Use the focused missing-data checklist for a step-by-step investigation.
Empty or incorrect visualization#
First prove that Samples contains representative events. Then rebuild:
- graph type: Single Line
- aggregation: Count
- metric: none
- split: none
- filters: none
- comparison: none
- range: broad
Add one control at a time. The first control that changes the result identifies the likely boundary.
Common causes:
| Symptom | Check |
|---|---|
| Sum or Avg is empty | Metric is a JSON number, not a numeric-looking string |
| Split is empty | Field is present and consistently a string |
| Counts differ by day | IANA time zone and exclusive range boundaries |
| Unexpected zero buckets | hideMissing customization and sparse data |
| Too many categories | High-cardinality split such as request or user ID |
| Comparison is empty | Comparison window has equivalent history |
| Nested field is absent | Flattening choice and exact dot-separated field name |
Export the chart as a Data API call and inspect the generated payload. The export is more reliable than manually reconstructing a complex configuration.
SQL queries#
Begin with the smallest possible query:
SELECT timestamp, json
FROM product_events
ORDER BY timestamp DESC
LIMIT 10
Then add extraction, filters, aggregation, and joins one at a time.
| Symptom | Likely cause |
|---|---|
| Unknown table | Collection name is wrong or used in an unsupported position |
| Unknown identifier | Alias or extracted column is unavailable at that query level |
| Empty extraction | Wrong field name or JSON type |
| Mutation error | Notebook is read-only |
| Result stops at 2,000 rows | Outer result guardrail |
| Query is slow | Wide scan, repeated JSON parsing, large join, or high-cardinality grouping |
| Chart tab is empty | Result columns are not mapped to the selected graph shape |
Use GraphJSON SQL compatibility for the supported surface and SQL performance and troubleshooting for query design.
Dashboards#
If one tile fails:
- open the tile’s source visualization or saved query
- verify its collection still exists
- verify the saved query still runs
- check the time range and time zone
- regenerate the tile only after the source works
If every tile fails, check account access and possible service status before editing each tile.
Stale-looking data may be a time-range issue or an embed cache boundary. Deleting and recreating a dashboard is rarely the right first response.
See Manage and share dashboards.
Embeds#
Separate URL generation from iframe rendering:
server generates URL
↓
browser receives only generated URL
↓
iframe loads GraphJSON result
If URL generation fails, inspect the server-side API status and redacted error. If generation succeeds but rendering fails:
- load the generated URL in an isolated test page
- confirm the iframe has a non-zero height
- inspect browser content-security-policy errors
- confirm the URL was not truncated or encoded twice
- verify the source chart still works
- allow for the documented 15-minute default cache TTL
If the embed shows the wrong tenant, stop distribution immediately. Verify that the server derives the account filter from the authenticated session and that every cache key includes the tenant and configuration version.
Use Production embedded analytics for the full security checklist.
Alerts#
An alert needs at least N + 1 primary result points. A relative alert needs N + 1 comparison points too.
If it does not evaluate:
- widen the visualization range
- reduce the alert window
- confirm the comparison returns data
- confirm the Single Line chart works
If it is active but no message is visible:
- determine whether it was already active before this evaluation
- inspect recent anomaly history
- verify recipient type and value
- check spam filtering or SMS restrictions
- remember that GraphJSON does not currently expose a delivery log or test-notification button
Use Create and operate alerts for the state machine and current limitations.
Integrations#
When provider events stop:
- confirm the integration still appears in GraphJSON
- confirm the destination collection still exists
- trigger a provider test event
- inspect the provider’s delivery or destination status
- check authentication or authorization changes at the provider
- check payload size and event selection
- compare the provider event ID with GraphJSON Samples
Provider retry behavior can produce duplicates. Preserve the provider event ID and reconcile it before treating counts as exact.
Use the provider guide under Integrations or the custom-source adapter guide.
Account access#
| Symptom | Action |
|---|---|
| Forgot password | Use Reset Password |
| Reset email absent | Check the exact account email and spam filtering |
| SMS code absent | Confirm country code, signal, and SMS availability |
| Lost access to enrolled phone | Contact support from the account email |
| Session expired | Sign in again and retry the original page |
| Former teammate still has access | Remove workspace access and rotate exposed shared credentials |
Password reset does not rotate the workspace API key. Team offboarding and API-key exposure are separate workflows.
See Account security and recovery.
Billing#
For an unexpected charge or usage value:
- open Settings
- record Events Stored
- open Manage Subscription
- inspect the invoice and billing period
- compare the invoice with the pricing page’s high-water-mark definition
- review recent imports, duplicates, retention changes, and test collections
Do not delete production data solely to investigate a bill. Export required records and understand that lowering current storage does not rewrite a previously recorded monthly high-water mark.
See Billing and subscription management.
Possible service incident#
Suspect a broader incident when several previously working, unrelated requests or surfaces fail at the same time and no deployment, key, collection, or account change explains them.
GraphJSON does not currently publish an automated public status feed or availability SLA. Check Service status and incident communication and send a safe incident report.
Keep product transactions independent of analytics availability. Queue important events and show an unavailable embed state rather than failing the customer’s primary action.
Build a safe support bundle#
Include:
account email:
workspace name:
approximate time and time zone:
endpoint or dashboard path:
collection:
HTTP status:
redacted error:
application event_id or provider event ID:
scope:
last known working time:
recent change:
retries and their outcome:
Exclude:
- API keys
- passwords and session tokens
- complete customer payloads
- full embed URLs
- payment-card or authentication data
- unrestricted raw exports
Email hi@graphjson.com. Begin with the metadata above; GraphJSON can request a narrower, secure sample if needed.