fix(db): make db-backup import size cap configurable (#4719) (#4757)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-23 07:34:43 -03:00
committed by GitHub
parent 5f4e9e73a4
commit a0c8eecbd1
3 changed files with 69 additions and 3 deletions

View File

@@ -8,6 +8,10 @@
_In development — bullets added per PR; finalized at release._
### 🔧 Bug Fixes
- **db-backups**: make the database-import size cap configurable via `OMNIROUTE_DB_IMPORT_MAX_MB` (default 100 MB, 4 GB ceiling) so backups larger than 100 MB can be restored; error message now points to the env var and to VACUUM (#4719).
---
## [3.8.34] — 2026-06-23

View File

@@ -11,7 +11,30 @@ import { getSettings } from "@/lib/db/settings";
import { setSystemPromptConfig } from "@omniroute/open-sse/services/systemPrompt.ts";
import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error";
const MAX_UPLOAD_SIZE = 100 * 1024 * 1024; // 100 MB
const DEFAULT_MAX_UPLOAD_MB = 100;
// Hard ceiling so a misconfigured/hostile value can't ask the route to buffer an
// unbounded file into memory.
const MAX_UPLOAD_MB_CEILING = 4096;
/**
* Resolve the maximum accepted backup size (bytes) from the environment.
*
* Real databases bloat well past the historical 100 MB cap (#4719 — a 156 MB file that
* VACUUMs down to 5 MB still can't be re-imported), so the limit is now operator-tunable
* via `OMNIROUTE_DB_IMPORT_MAX_MB`. Invalid / out-of-range values fall back to the 100 MB
* default and are clamped to a 4 GB ceiling.
*/
export function resolveMaxUploadSizeBytes(
env: NodeJS.ProcessEnv = process.env
): number {
const raw = env.OMNIROUTE_DB_IMPORT_MAX_MB;
const parsed = raw === undefined ? NaN : Number(raw);
const mb =
Number.isFinite(parsed) && parsed >= 1
? Math.min(Math.floor(parsed), MAX_UPLOAD_MB_CEILING)
: DEFAULT_MAX_UPLOAD_MB;
return mb * 1024 * 1024;
}
// Required tables that must exist in a valid OmniRoute database
const REQUIRED_TABLES = ["provider_connections", "provider_nodes", "combos", "api_keys"];
@@ -68,10 +91,15 @@ export async function POST(request: Request) {
}
// Validate file size
const maxUploadSize = resolveMaxUploadSizeBytes();
const fileSize = fileBuffer.length;
if (fileSize > MAX_UPLOAD_SIZE) {
if (fileSize > maxUploadSize) {
return NextResponse.json(
{ error: `File too large. Maximum allowed size is ${MAX_UPLOAD_SIZE / (1024 * 1024)} MB.` },
{
error:
`File too large. Maximum allowed size is ${maxUploadSize / (1024 * 1024)} MB. ` +
`Set OMNIROUTE_DB_IMPORT_MAX_MB to raise it, or VACUUM the database before exporting.`,
},
{ status: 400 }
);
}

View File

@@ -0,0 +1,34 @@
// #4719 — DB backup import failed for databases larger than the hard-coded 100 MB cap.
// Real databases bloat (a 156 MB file VACUUMs down to 5 MB) but still couldn't be
// re-imported. The cap is now operator-tunable via OMNIROUTE_DB_IMPORT_MAX_MB, with the
// historical 100 MB as default and a 4 GB ceiling for invalid/hostile values.
import test from "node:test";
import assert from "node:assert/strict";
const { resolveMaxUploadSizeBytes } = await import(
"../../src/app/api/db-backups/import/route.ts"
);
const MB = 1024 * 1024;
test("defaults to 100 MB when env is unset (#4719)", () => {
assert.equal(resolveMaxUploadSizeBytes({}), 100 * MB);
});
test("honors OMNIROUTE_DB_IMPORT_MAX_MB (#4719)", () => {
assert.equal(resolveMaxUploadSizeBytes({ OMNIROUTE_DB_IMPORT_MAX_MB: "256" }), 256 * MB);
});
test("clamps absurd values to the 4 GB ceiling (#4719)", () => {
assert.equal(resolveMaxUploadSizeBytes({ OMNIROUTE_DB_IMPORT_MAX_MB: "999999" }), 4096 * MB);
});
test("falls back to default for invalid / out-of-range values (#4719)", () => {
assert.equal(resolveMaxUploadSizeBytes({ OMNIROUTE_DB_IMPORT_MAX_MB: "abc" }), 100 * MB);
assert.equal(resolveMaxUploadSizeBytes({ OMNIROUTE_DB_IMPORT_MAX_MB: "0" }), 100 * MB);
assert.equal(resolveMaxUploadSizeBytes({ OMNIROUTE_DB_IMPORT_MAX_MB: "-5" }), 100 * MB);
});
test("floors fractional MB values (#4719)", () => {
assert.equal(resolveMaxUploadSizeBytes({ OMNIROUTE_DB_IMPORT_MAX_MB: "150.9" }), 150 * MB);
});