Make debug-migration GET a robust pgvector/migration diagnostic

Each probe now runs independently (pgvector check first and standalone) and
reads the drizzle journal from the correct "drizzle" schema, so the endpoint
returns a usable diagnostic instead of crashing on the first missing relation.
Also reports whether error_events exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Manohar Gupta 2026-05-30 08:59:16 +05:30
parent 91c25b2c15
commit 05975b51a1

View file

@ -6,29 +6,54 @@ export async function GET() {
const auth = await requireFamily();
if (!auth.success) return NextResponse.json({ error: auth.error }, { status: auth.status });
// Each probe is independent so one failure never blanks the whole diagnostic.
const out: Record<string, unknown> = {};
// pgvector status — FIRST and standalone (this is what diagnoses the
// "could not access file vector" production error). pg_available_extensions
// reads the on-disk extension catalog and never loads the vector library, so
// it works even when the image is missing the pgvector binaries.
try {
const migrations = await sql.unsafe(
`SELECT hash, created_at FROM __drizzle_migrations ORDER BY created_at DESC LIMIT 10`
);
const circleTables = await sql.unsafe(
`SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND (tablename LIKE 'circle%' OR tablename = 'post_reports') ORDER BY tablename`
);
// pgvector status: is the binary available in this Postgres image, and is
// the extension actually created? (diagnoses "could not access file vector")
const vectorRows = await sql.unsafe(
`SELECT name, default_version, installed_version FROM pg_available_extensions WHERE name = 'vector'`
);
const v = vectorRows[0] as { default_version?: string; installed_version?: string } | undefined;
const pgvector = {
binaryAvailable: !!v, // false → wrong Postgres image (no pgvector)
out.pgvector = {
binaryAvailable: !!v, // false → wrong Postgres image (no pgvector binaries)
installed: !!v?.installed_version, // false → needs CREATE EXTENSION vector
availableVersion: v?.default_version ?? null,
installedVersion: v?.installed_version ?? null,
};
return NextResponse.json({ migrations, circleTables, pgvector });
} catch (err: unknown) {
return NextResponse.json({ error: err instanceof Error ? err.message : String(err) });
} catch (e) {
out.pgvectorError = String(e);
}
// Does the error_events table exist yet? (admin Errors page depends on it)
try {
const r = await sql.unsafe(`SELECT to_regclass('public.error_events') AS reg`);
out.errorEventsExists = !!(r[0] as { reg?: string })?.reg;
} catch (e) {
out.errorEventsError = String(e);
}
// Applied drizzle migrations (the journal lives in the "drizzle" schema).
try {
out.migrations = await sql.unsafe(
`SELECT hash, created_at FROM drizzle.__drizzle_migrations ORDER BY created_at DESC LIMIT 12`
);
} catch (e) {
out.migrationsError = String(e);
}
try {
out.circleTables = await sql.unsafe(
`SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND (tablename LIKE 'circle%' OR tablename = 'post_reports') ORDER BY tablename`
);
} catch (e) {
out.circleTablesError = String(e);
}
return NextResponse.json(out);
}
// One-shot: apply circles migration via the app DB connection (requires login)