reference · troubleshooting
Troubleshooting
This page lists 23 problems as a symptom and its fix side by side, covering authentication, connection, schema registration, row inserts, SQL, vector, full-text, graph, rate limits and PITR restore. Search it (⌘F / Ctrl-F) for your exact error message.
For error codes specifically, see Error reference. For rate-limit issues, see Rate limits. If you don't find your problem here, email support@originchain.ai with the X-OC-Trace-Id from the response headers.
| Problem | Symptom + fix |
|---|---|
| 401 unauthorized on every call | Symptom: Bearer token rejected even though you copied it from the dashboard. Fix: Token may have been truncated (often by Slack or terminals trimming spaces). Open the dashboard's token panel and copy again. Also check the endpoint hostname matches the token's instance - tokens are per-instance. |
| Cannot connect to host | Symptom: DNS or TLS errors before any request lands. Fix: Verify OC_HOST is the full hostname (e.g. acme.db.originchain.ai), not just the tenant id. The dashboard's 'Connect' panel shows the right URL. |
| Schema registration returns 400 'unknown column type' | Symptom: Trying ty = 'ulid' / 'string' / 'int' - spellings borrowed from another database. Fix: decimal, timestamp and vector are all valid - it is the aliases that are not. The type names are i64, u64, f64, bool, str, text, bytes, timestamp, date, time, uuid, decimal, enum, json, list, inet, interval, point and vector. So ulid is str, string is str and int is i64. See Schemas reference. |
| Schema registration returns 400 'invalid type: string, expected struct' | Symptom: Relation target was written as a single string, e.g. target = 'shop.suppliers'. Fix: target is a sub-table: [relations.target] namespace = '...' table = '...' pk = '...'. See Schemas → relations. |
| [[extractions.fts]] and [[extractions.vector]] blocks ignored | Symptom: Register succeeds but vector / FTS data never appears. Fix: Those blocks aren't real - they don't exist in the schema grammar. FTS indexes via POST /v1/tenants/:t/fts/:table/:field. Vectors via POST /v1/tenants/:t/vector/:table/put. |
| Row insert returns 400 type_mismatch | Symptom: Specific field named in the error message. Fix: Check that the JSON value's type matches the column's declared ty. Numbers can't be sent as JSON strings. Booleans need to be true / false, not 'true' / 'false'. |
| Row insert returns 400 fk_violation | Symptom: Foreign-key column points at a row that doesn't exist. Fix: Insert the target row first. If you really want orphan references (unusual), drop the foreign-key constraint from the schema. |
| Bulk insert is much slower than expected | Symptom: Single-row inserts in a loop instead of using _batch. Fix: Use POST /rows/:schema/_batch with a JSON array (up to ~8 MiB) or NDJSON (no cap, streamed). See Insert → bulk. |
| Duplicate rows after a network retry | Symptom: Single-row insert succeeded server-side but the client thought it failed and retried. Fix: Pass an Idempotency-Key header on every mutating call (or use the SDKs - they do this automatically). The engine dedupes retries within 24h. |
| HAVING or a window function over a JOIN returns 400 | Symptom: A grouped or windowed query runs on one table, then fails once a JOIN is added. Fix: Plain HAVING and window functions ship. What is still refused is the join-shaped combination: HAVING across a JOIN, a DISTINCT aggregate over a JOIN, and a window function in the same SELECT as a JOIN. Aggregate one side first, then join. See SQL reference. |
| Vector topk returns 400 dim_mismatch | Symptom: Query vector length doesn't match the table's locked dim. Fix: Every vector in a table has the same length, set by the first put. If you switched models, you need a new table. |
| Vector topk returns 400 metric_mismatch | Symptom: Used a different distance metric than the table's first put. Fix: Pick cosine / dot / l2 / manhattan once per table. Cosine is the right default for most text embeddings. |
| Vector search returns fewer than k hits | Symptom: Asked for k=50 but got back 12. Fix: Either the table has fewer than 50 vectors, or your metadata filter is highly selective. Both are expected behaviour - it's not a bug. |
| FTS search returns no hits for words that should match | Symptom: Text was indexed; query has the right words. Fix: Likely an analyzer mismatch. Stemming / lowercase / accent folding must be the same at index and query time. Re-check the analyzer configured on the (table, field). |
| FTS hits link to rows that don't exist | Symptom: Search returns doc_ids, but GET /rows/:schema/:doc_id is 404. Fix: FTS indexes are independent of rows. Either the row was deleted (didn't trigger an FTS removal) or the indexed doc_id was never a real row PK to begin with. Re-issue the index call with current doc_ids. |
| Graph neighbors returns empty | Symptom: Schema has relation declared, rows are written, but graph endpoints return no neighbors. Fix: Confirm the relation's from_col matches the column actually populated on the row. Rows written before the relation was declared don't have edges - re-write them to materialize. |
| BFS takes a long time / times out | Symptom: Calling /bfs without max_depth or with a very large depth. Fix: Always cap max_depth at the smallest value that gives useful results. On dense graphs, depth=5 can return millions of nodes. |
| 429 rate_limited on legitimate traffic | Symptom: Burst traffic during a scheduled job. Fix: Honor Retry-After. For sustained high throughput, request a limit increase (support@originchain.ai). For one-time imports, use _batch instead of single-row inserts. |
| Replication lag visible in the dashboard | Symptom: Reads occasionally see stale data after writes. Fix: Reads are routed to the primary by default - they see writes immediately. If you're explicitly reading from a replica, accept eventual consistency. For strict read-after-write, read from the primary endpoint. |
| PITR restore is taking longer than expected | Symptom: Restore in progress, ETA unknown. Fix: PITR is bounded by your recovery-point retention window (typically 7-30 days). Larger windows take longer to scan. Watch progress in the dashboard's Restore panel. |