abhigyanpatwari/GitNexus · error
Prepare failed
Error message
Prepare failed: ${errMsg} What it means
executePrepared (gitnexus/src/core/lbug/lbug-adapter.ts:1798) runs the prepare/execute pattern on the singleton writable connection. c.prepare(cypher) returned a non-success PreparedStatement, so the LadybugDB parser rejected the statement, and the engine's own error text is appended. This is a query-shape problem (syntax, unknown table/property, bad parameter usage), not an IO failure.
Solutions
- Read the appended engine message — it names the parser error and the offending token or table
- If the table is missing because the index predates a schema-changing version, re-run gitnexus analyze to rebuild it
- Check every $placeholder has a matching params key (and vice versa) before calling
- Escape reserved table names with backticks (escapeTableName) and use exact schema spellings for properties
Example fix
// before — placeholder does not match the params key
await executePrepared('MATCH (f:File) WHERE f.path = $path RETURN f', { filePath });
// after — placeholder names must match params keys exactly
await executePrepared('MATCH (f:File) WHERE f.path = $path RETURN f', { path: filePath }); Defensive patterns
Strategy: validation
Validate before calling
// validate placeholders and params keys line up before preparing
const placeholders = [...cypher.matchAll(/\$(\w+)/g)].map((m) => m[1]);
const missing = placeholders.filter((p) => !(p in params));
if (missing.length > 0) {
throw new Error(`params missing keys used by the query: ${missing.join(', ')}`);
} Type guard
const isPrepareFailed = (e: unknown): boolean =>
e instanceof Error && e.message.startsWith('Prepare failed:'); Try / catch
try {
rows = await executePrepared(cypher, params);
} catch (e) {
if (isPrepareFailed(e)) {
// parser rejected the statement — surface the engine text, do not retry the same string
throw new Error(`bad Cypher (${e.message}); query: ${cypher.slice(0, 120)}`);
}
throw e;
} Prevention
- Keep Cypher templates as constants co-versioned with the schema they target
- Rebuild the index after upgrading GitNexus versions that change table or property names
- Always bind values via $parameters instead of string interpolation
When it happens
Trigger: Calling executePrepared(cypher, params) with Cypher that references a node or relationship table absent from the open index, a misspelled property, a syntax error, or $placeholders that do not match the keys of the params object.
Common situations: Schema drift — querying with a newer GitNexus version's table/property names against an index built by an older one; dynamically built queries with unescaped reserved identifiers; querying tables before analyze has created them.
Related errors
- Bridge query prepare failed
- Batch execution failed for rows
- Connection pool integrity error: expected
- Failed to remove the LadybugDB index files — still present…
- FTS extension unavailable - cannot create FTS index
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-08-20).
Data as JSON: /api/errors/dc19b1705f1dbc79.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/core/lbug/lbug-adapter.ts:1910
/**
* Execute a single parameterized query (prepare/execute pattern).
* Prevents Cypher injection by binding values as parameters.
*/
export const executePrepared = async (
cypher: string,
params: Record<string, any>,
): Promise<any[]> => {
// A `.length` compare on text we already hold; never throws (#2915).
warnIfQueryTextUnbounded(cypher, 'executePrepared', (message) => logger.warn(message));
const c = conn;
if (!c) {
throw new Error('LadybugDB not initialized. Call initLbug first.');
}
return withConnLock(async () => {
const stmt = await c.prepare(cypher);
if (!stmt.isSuccess()) {
const errMsg = await stmt.getErrorMessage();
throw new Error(`Prepare failed: ${errMsg}`);
}
const queryResult = await c.execute(stmt, params);
return await readQueryRows(queryResult);
});
};
export const executeWithReusedStatement = async (
cypher: string,
paramsList: Array<Record<string, any>>,
): Promise<void> => {
const c = conn;
if (!c) {
throw new Error('LadybugDB not initialized. Call initLbug first.');
}
if (paramsList.length === 0) return;
const SUB_BATCH_SIZE = 4;
for (const [subBatchIndex, subBatch] of chunk(paramsList, SUB_BATCH_SIZE).entries()) {View on GitHub (pinned to ac9a4e9abd)