Troubleshooting
This guide covers common issues and their solutions when working with TypeGraph.
Installation Issues
Section titled “Installation Issues””Cannot find module ‘@nicia-ai/typegraph’”
Section titled “”Cannot find module ‘@nicia-ai/typegraph’””Cause: Package not installed or using wrong package name.
Solution:
npm install @nicia-ai/typegraph zod drizzle-orm“better-sqlite3 compilation failed”
Section titled ““better-sqlite3 compilation failed””Cause: Native module compilation requires build tools.
Solutions:
macOS:
xcode-select --installUbuntu/Debian:
sudo apt-get install build-essential python3Windows:
npm install --global windows-build-toolsAlternative: Use sql.js for pure JavaScript SQLite (no compilation needed).
”Module not found: drizzle-orm/better-sqlite3”
Section titled “”Module not found: drizzle-orm/better-sqlite3””Cause: Drizzle ORM subpath exports require specific import syntax.
Solution: Ensure correct imports:
// Correctimport { drizzle } from "drizzle-orm/better-sqlite3";
// Incorrectimport { drizzle } from "drizzle-orm";Schema Definition Errors
Section titled “Schema Definition Errors””Node schema contains reserved property names”
Section titled “”Node schema contains reserved property names””Cause: Using reserved keys (id, kind, meta) in your Zod schema.
Solution: Rename your properties:
// Bad - 'id' is reservedconst User = defineNode("User", { schema: z.object({ id: z.string(), // Error! name: z.string(), }),});
// Good - use a different nameconst User = defineNode("User", { schema: z.object({ externalId: z.string(), name: z.string(), }),});TypeGraph automatically provides id, kind, and meta on all nodes.
”Edge type already has constraints defined”
Section titled “”Edge type already has constraints defined””Cause: Defining from/to constraints on both the edge type and graph registration.
Solution: Define constraints in one place only:
// Option 1: On the edge type (reusable across graphs)const worksAt = defineEdge("worksAt", { from: [Person], to: [Company],});
const graph = defineGraph({ edges: { worksAt: { type: worksAt }, // No from/to here },});
// Option 2: On the graph (flexible per-graph)const worksAt = defineEdge("worksAt");
const graph = defineGraph({ edges: { worksAt: { type: worksAt, from: [Person], to: [Company] }, },});Runtime Errors
Section titled “Runtime Errors”ValidationError: “Invalid input”
Section titled “ValidationError: “Invalid input””Cause: Data doesn’t match the Zod schema.
Solution: Check the error details for specific issues:
try { await store.nodes.Person.create({ name: "" });} catch (error) { if (error instanceof ValidationError) { console.log(error.details.issues); // Zod issues array }}NodeNotFoundError
Section titled “NodeNotFoundError”Cause: Attempting to read/update/delete a non-existent node.
Solution: Check if the node exists first or handle the error:
const node = await store.nodes.Person.getById(someId);if (!node) { // Handle missing node}
// Or use error handlingtry { await store.nodes.Person.update(someId, { name: "New" });} catch (error) { if (error instanceof NodeNotFoundError) { console.log(`Node ${error.details.id} not found`); }}RestrictedDeleteError
Section titled “RestrictedDeleteError”Cause: Attempting to delete a node that has edges, with onDelete: "restrict" (the default).
Solution: Either delete the edges first or use a different delete behavior:
// Option 1: Delete edges firstconst edges = await store.edges.worksAt.findFrom(person);for (const edge of edges) { await store.edges.worksAt.delete(edge.id);}await store.nodes.Person.delete(person.id);
// Option 2: Use cascade delete in schemaconst graph = defineGraph({ nodes: { Person: { type: Person, onDelete: "cascade" }, },});DisjointError
Section titled “DisjointError”Cause: Creating a node with an ID that’s already used by a disjoint type.
Solution: Ensure IDs are unique across disjoint types or don’t use explicit IDs:
// If Person and Organization are disjoint:// Bad - same ID for different typesawait store.nodes.Person.create({ name: "Alice" }, { id: "entity-1" });await store.nodes.Organization.create({ name: "Acme" }, { id: "entity-1" }); // Error!
// Good - let TypeGraph generate unique IDsawait store.nodes.Person.create({ name: "Alice" });await store.nodes.Organization.create({ name: "Acme" });Query Issues
Section titled “Query Issues””Alias ‘x’ is already in use”
Section titled “”Alias ‘x’ is already in use””Cause: Using the same alias twice in a query.
Solution: Use unique aliases:
// Badstore.query() .from("Person", "p") .traverse("knows", "e") .to("Person", "p") // Error! 'p' already used
// Goodstore.query() .from("Person", "p1") .traverse("knows", "e") .to("Person", "p2")Empty results when expecting data
Section titled “Empty results when expecting data”Causes and solutions:
-
Type mismatch: Ensure you’re querying the correct node type
// Check the node type name matches exactly.from("Person", "p") // Must match defineNode("Person", ...) -
Missing includeSubClasses: When querying a superclass
.from("Content", "c", { includeSubClasses: true }) -
Strict predicate: Check your filters aren’t too restrictive
// Debug by removing filters temporarilyconst all = await store.query().from("Person", "p").select((c) => c.p).execute();console.log(all.length); // How many total?
Slow queries
Section titled “Slow queries”Solutions:
-
Use the query profiler:
import { QueryProfiler } from "@nicia-ai/typegraph/profiler";const profiler = new QueryProfiler();profiler.attachToStore(store);// Run your queries...const report = profiler.getReport();console.log(report.recommendations); -
Add indexes based on profiler recommendations:
import { defineNodeIndex } from "@nicia-ai/typegraph/indexes";const nameIndex = defineNodeIndex("Person", ["name"]); -
Limit results:
.limit(100)// Or use pagination.paginate({ first: 20 })
Database Connection Issues
Section titled “Database Connection Issues””Database is locked” (SQLite)
Section titled “”Database is locked” (SQLite)”Cause: Multiple processes accessing the same SQLite file without WAL mode.
Solution: Enable WAL mode:
const sqlite = new Database("myapp.db");sqlite.pragma("journal_mode = WAL");Connection pool exhausted (PostgreSQL)
Section titled “Connection pool exhausted (PostgreSQL)”Cause: Too many concurrent connections.
Solution: Configure pool limits:
import { Pool } from "pg";
const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 20, // Adjust based on your needs idleTimeoutMillis: 30000,});“relation ‘typegraph_nodes’ does not exist”
Section titled ““relation ‘typegraph_nodes’ does not exist””Cause: Migration not run.
Solution: Run the migration SQL:
// PostgreSQLimport { generatePostgresMigrationSQL } from "@nicia-ai/typegraph/postgres";await pool.query(generatePostgresMigrationSQL());
// SQLiteimport { generateSqliteMigrationSQL } from "@nicia-ai/typegraph/sqlite";sqlite.exec(generateSqliteMigrationSQL());Semantic Search Issues
Section titled “Semantic Search Issues””Extension not found” / “vector type not available”
Section titled “”Extension not found” / “vector type not available””Cause: Vector extension not installed.
PostgreSQL:
CREATE EXTENSION IF NOT EXISTS vector;SQLite:
import * as sqliteVec from "sqlite-vec";sqliteVec.load(sqlite); // Must be called before creating backend“Dimension mismatch”
Section titled ““Dimension mismatch””Cause: Query embedding has different dimension than stored embeddings.
Solution: Use consistent embedding dimensions:
// Schema defines 1536 dimensionsconst Document = defineNode("Document", { schema: z.object({ embedding: embedding(1536), }),});
// Query embedding must also be 1536const queryEmbedding = await generateEmbedding(text);console.log(queryEmbedding.length); // Should be 1536“Inner product not supported” (SQLite)
Section titled ““Inner product not supported” (SQLite)”Cause: sqlite-vec doesn’t support inner product metric.
Solution: Use cosine or L2:
// Instead of:d.embedding.similarTo(query, 10, { metric: "inner_product" })
// Use:d.embedding.similarTo(query, 10, { metric: "cosine" })TypeScript Issues
Section titled “TypeScript Issues””Property ‘x’ does not exist on type”
Section titled “”Property ‘x’ does not exist on type””Cause: Accessing a property not defined in your schema.
Solution: Ensure the property is in your Zod schema:
const Person = defineNode("Person", { schema: z.object({ name: z.string(), email: z.string().optional(), }),});
// Now both properties are available with correct typesconst person = await store.nodes.Person.getById(id);person?.name; // stringperson?.email; // string | undefinedType inference not working in select
Section titled “Type inference not working in select”Cause: Complex generic inference limitations.
Solution: Use explicit typing or simplify:
// If inference fails, be explicit.select((ctx) => ({ name: ctx.p.name as string, company: ctx.c.name as string,}))Still Having Issues?
Section titled “Still Having Issues?”- Check the Limitations page for known constraints
- Review Architecture to understand how TypeGraph works
- Search GitHub Issues for similar problems
- Open a new issue with a minimal reproduction case