Troubleshooting Guide¶
This guide covers common issues, error messages, and their solutions when working with Uni.
Quick Diagnostics¶
# Check database info
uni query "SHOW DATABASE" --path ./storage
# Check schema
uni query "CALL uni.schema.labels() YIELD label RETURN label" --path ./storage
# Basic stats
uni query "SHOW STATISTICS" --path ./storage
# View recent logs
RUST_LOG=uni_db=debug uni query "RETURN 1" --path ./storage 2>&1 | tail -50
Common Issues¶
Installation Problems¶
Rust Version Incompatible¶
Symptom:
Solution:
Missing System Dependencies¶
Symptom:
Solution:
# Ubuntu/Debian
sudo apt install pkg-config libssl-dev
# macOS
brew install openssl
export OPENSSL_DIR=$(brew --prefix openssl)
# Fedora
sudo dnf install openssl-devel
Build Fails with SIMD Errors¶
Symptom:
Solution:
# Build without SIMD optimizations
cargo build --release --no-default-features
# Or specify target CPU
RUSTFLAGS="-C target-cpu=native" cargo build --release
Storage Issues¶
Cannot Open Storage¶
Symptom:
Solution:
# Check path exists
ls -la ./storage
# Create storage (embedded mode)
uni query "RETURN 1" --path ./storage
Corrupted Storage¶
Symptom:
Solution:
# Restore from snapshot (recommended)
uni snapshot list --path ./storage
uni snapshot restore <snapshot_id> --path ./storage
# Or via Cypher
uni query "CALL uni.admin.snapshot.list()" --path ./storage
uni query "CALL uni.admin.snapshot.restore('<snapshot_id>')" --path ./storage
# If no snapshot exists, re-import or rebuild the database
Out of Disk Space¶
Symptom:
Solution:
# Check disk usage
df -h ./storage
# Compact storage
uni query "CALL uni.admin.compact()" --path ./storage
# Move storage to a larger disk (stop any running processes first)
mv ./storage /larger-disk/storage
Query Issues¶
Parse Errors¶
Symptom:
Common Causes:
- Missing quotes around strings:
- Wrong comparison operator:
- Missing relationship direction:
Semantic Errors¶
Symptom:
Solution:
# List available labels
uni query "CALL uni.schema.labels() YIELD label RETURN label" --path ./storage
# Check spelling/case
# Labels are case-sensitive: Paper != paper
Symptom:
Solution:
# List properties for label
uni query "CALL uni.schema.labelInfo('Paper')" --path ./storage
# Add property to schema if needed
uni query "ALTER LABEL Paper ADD PROPERTY year INT32" --path ./storage
Query Timeout¶
Symptom:
Solutions:
-
Add LIMIT:
-
Add filters:
-
Increase timeout:
-
Check query plan:
Out of Memory¶
Symptom:
Solutions:
-
Reduce result size:
-
Stream results:
-
Increase memory limit:
-
Reduce batch size:
Index Issues¶
Vector Search Returns Poor Results¶
Symptom: Results are not semantically similar to the query.
Causes and Solutions:
- Embedding model mismatch: Ensure the same embedding model is used for indexing and querying.
-
Auto-embedding routes through any provider in the catalog.
local/candle(BERT-style) andlocal/onnx(FastEmbed-compatible alias strings via the unified ONNX Embed task) are the two local backends. Remote APIs (OpenAI, Gemini, Vertex, Voyage, Cohere) are supported through their respectiveprovider-*features. -
Dimension mismatch: since 2.5.0 this surfaces as an error, not as poor results — a query vector whose length differs from the declared column dimension fails with "vector dimension mismatch" (previously it silently returned 0 rows), and wrong-length writes fail with a
TypeError. -
Index mismatch or missing index:
If you need a different distance metric, recreate the index via Rust/Python APIs (Cypher DDL uses cosine today).
Index Not Being Used¶
Symptom: Query is slow despite having an index.
Diagnosis:
Common Causes:
- Function on indexed column:
// Index NOT used (function applied to column)
WHERE LOWER(p.venue) = 'neurips'
// Index used
WHERE p.venue = 'NeurIPS'
- OR conditions:
// May not use index efficiently
WHERE p.year > 2020 OR p.venue = 'NeurIPS'
// Better: split into UNION (if supported)
- Leading wildcard:
- Low selectivity:
Index Build Fails¶
Symptom:
Solutions:
-
Use IVF_PQ or Flat instead of HNSW:
-
Build asynchronously after bulk load:
Or usebulk_writer().async_indexes(true).
Import Issues (CLI)¶
The CLI importer expects the Semantic Scholar demo format (vid, src_vid, dst_vid).
Missing Required Fields¶
Symptom:
Solution: Ensure your JSONL includes:
- Papers: vid, title, year, citation_count, embedding
- Citations: src_vid, dst_vid
Invalid VID References¶
Symptom:
Solution: Ensure citations reference existing paper VIDs.
Embedding Dimension Mismatch¶
Symptom:
Solution:
If you need a different dimension, create a new label/property and re-import.Performance Issues¶
Slow Traversals¶
Symptom: Graph traversals take >100ms.
Diagnosis:
Solutions:
-
Warm the adjacency cache:
-
Increase cache size:
-
Add LIMIT to multi-hop:
-
Stop asking for whole paths. A variable-length pattern only expands individual paths when the query binds one. Returning endpoints skips that work entirely, and on a graph with cycles the difference is not marginal — the number of distinct paths grows combinatorially with the hop bound while the underlying search does not.
// Expensive: every distinct path is built
MATCH p = (a:Paper)-[:CITES*1..6]->(b) RETURN p
// Cheap: same search, no path expansion
MATCH (a:Paper)-[:CITES*1..6]->(b) RETURN DISTINCT b
If you want one path rather than all of them, use shortestPath, which
stops at the first one it finds.
A Path Query Times Out or Exhausts Memory¶
Symptom: MATCH p = (a)-[:R*]->(b) RETURN p (or count(p)) fails with a
timeout or a ResourcesExhausted error, while the same pattern returning
endpoints succeeds.
Cause: This is path expansion, not the graph search. Over a cyclic graph the set of distinct paths is combinatorial, so the query is asking for an unbounded amount of work. The error names whichever declared limit stopped it.
Solutions, in order of effectiveness:
- Return endpoints instead of
p— see above. Usually this is the whole fix. - Add a
LIMIT. It stops the expansion rather than trimming its output, so a small limit costs a small amount of work. Note the floor: the graph search still runs in full, and the limit applies a batch (8192 rows) at a time, so any limit up to 8192 costs the same. - Write an upper hop bound —
[*1..6]rather than[*]. Remember an omitted bound means 100, not infinity. - Raise the ceiling only once the above are exhausted:
query_with(...).max_memory(...)/.timeout(...).
If rows come back with a warning about a safety cap instead, that is a different condition: the search was abandoned and the results are incomplete. Narrow the pattern with a hop bound, a relationship type, or a label on the target.
High Memory Usage¶
Symptom: Process using more memory than expected.
Diagnosis: Use OS-level tools (top, htop) and PROFILE output.
Solutions:
-
Reduce cache sizes:
-
Flush L0 more frequently:
-
Use streaming queries:
Error Reference¶
Storage / IO Errors¶
| Error | Cause | Solution |
|---|---|---|
DatabaseLocked |
Another process holds the lock | Close other process or use a different path |
ReadOnly |
Write attempted on a read-only database | Open in write mode or avoid writes |
Storage |
Underlying storage failure | Check storage config/permissions |
Io |
OS I/O error (e.g., disk full) | Fix disk/permissions |
NotFound |
Database path does not exist | Create the DB or fix the path |
Query / Schema Errors¶
| Error | Cause | Solution |
|---|---|---|
Parse |
Invalid Cypher syntax | Fix query syntax |
Schema |
Invalid schema definition | Fix schema input |
LabelNotFound |
Label not in schema | Check schema or create label |
EdgeTypeNotFound |
Edge type not in schema | Check schema or create edge type |
PropertyNotFound |
Property not in schema | Check schema or fix query |
Type |
Incompatible types (e.g., vector dims mismatch) | Fix query or data types |
InvalidArgument |
Invalid procedure argument | Fix argument values |
IndexNotFound |
Index does not exist | Create index first |
Constraint |
Constraint violation | Fix data or drop constraint |
Timeout |
Query exceeded time limit | Optimize query or increase timeout |
MemoryLimitExceeded |
Memory limit exceeded | Reduce result size or increase limit |
Debugging Tips¶
Enable Verbose Logging¶
# All Uni logs at debug level
RUST_LOG=uni_db=debug uni query "..." --path ./storage
# Specific module
RUST_LOG=uni_db::storage=trace,uni_db::query=debug uni query "..."
# Include Lance logs
RUST_LOG=uni_db=debug,lance=info uni query "..."
Query Profiling¶
# Get execution profile
uni query "PROFILE MATCH (p:Paper) WHERE p.year > 2020 RETURN COUNT(p)" --path ./storage
# Output shows:
# - Time per operator
# - Rows processed
# - Index usage
# - Memory usage
Storage Inspection¶
# List all datasets
ls -la ./storage/vertices/
ls -la ./storage/edges/
ls -la ./storage/adjacency/
# Check Lance dataset info
# View on-disk schema
cat ./storage/catalog/schema.json | jq .
Memory Profiling¶
# Run with verbose logging
RUST_LOG=uni_db=debug uni query "..."
# Use heaptrack (Linux)
heaptrack uni query "..."
heaptrack_gui heaptrack.uni.*.gz
Getting Help¶
Resources¶
- Documentation: https://rustic-ai.github.io/uni-db/
- GitHub Issues: https://github.com/rustic-ai/uni-db/issues
- Discussions: https://github.com/rustic-ai/uni-db/discussions
Reporting Bugs¶
When reporting issues, include:
- Uni version:
uni --version - Rust version:
rustc --version - OS and version
- Minimal reproduction steps
- Error messages (full output)
- Query plan (if query-related):
EXPLAIN ... - Storage stats:
uni stats --path ./storage
Next Steps¶
- Configuration Reference — All configuration options
- Performance Tuning — Optimization strategies
- Glossary — Terminology reference