content icon indicating copy to clipboard operation
content copied to clipboard

[Bug]: SQLite ":memory:" config fails because colon is stripped but Bun connector expects it

Open malformed-c opened this issue 1 month ago • 0 comments

Environment

Operating system Linux 6.17.9-zen1-1-zen
CPU Intel(R) Core(TM) i5-8365U CPU @ 1.60GHz (8 cores)
Node.js version v25.2.1
nuxt/cli version 3.31.2-20251205-111428-3650f92
Package manager [email protected]
Nuxt version 4.2.2-29413365.2a912219
Nitro version 2.12.9
Builder [email protected]
Config app, colorMode, compatibilityDate, content, css, devtools, experimental, fonts, modules, nitro, routeRules, runtimeConfig, svgo, ui, vite
Modules @nuxt/[email protected], @nuxt/[email protected], @nuxt/[email protected], @nuxt/[email protected], @nuxt/[email protected], [email protected]

Version

v3

Reproduction

I'll provide the repository if needed.

  1. Configure Nuxt Content with sqlite and filename: ":memory:".
  2. Run in a read-only environment (or Docker container).
  3. Observe SQLITE_CANTOPEN error because it tries to write to disk instead of using memory.

Description

I am deploying Nuxt Content v3 on Kubernetes using the Bun runtime. I am trying to use an in-memory SQLite database to avoid file system permission issues in the container. However, setting filename: ":memory:" triggers a logic error where the configuration parser strips the colon, but the connector checks strictly for ":memory:". This causes the application to fall through to the file-system creation logic, attempting to write a file named .data/memory.bun.sqlite, which it's unable to do due to permissions.

Additional context

related snippet 1

function refineDatabaseConfig(config) {
...
  if (config.type === "sqlite") {
    const _config = { ...config };
    if (config.filename === ":memory:") {
      return { name: "memory" }; // <--- Returns "memory" without colon
    }
    if ("filename" in config) {
      const filename = isAbsolute(config?.filename || "") || config?.filename === ":memory:" ? config?.filename : new URL(config.filename, globalThis._importMeta_.url).pathname;
      _config.path = process.platform === "win32" && filename.startsWith("/") ? filename.slice(1) : filename;
    }
    return _config;
  }

related snippet 2

function bunSqliteConnector(opts) {
  let _db;
  const getDB = () => {
    if (_db) {
      return _db;
    }
    if (opts.name === ":memory:") { // <--- Checks for ":memory:"
      _db = new Database(":memory:");
    } else {
      const filePath = resolve$1(opts.cwd || ".", opts.path || `.data/${opts.name || "db"}.bun.sqlite`);
      mkdirSync(dirname$1(filePath), { recursive: true });
      _db = new Database(filePath);
    }
    return _db;
  };

Logs

[request error] [unhandled] [POST] http://localhost/__nuxt_content/faq/query?v=v3.5.0--uOI5oD1lVvnPvQrq99B90r2Ef0ddCNWLK-rmPNHVtbk
 7170 |                 if (opts.name === ":memory:") {
7171 |                  _db = new Database(":memory:");
7172 |          } else {
7173 |                  const filePath = resolve$1(opts.cwd || ".", opts.path || `.data/${opts.name || "db"}.bun.sqlite`);
7174 |                  mkdirSync(dirname$1(filePath), { recursive: true });
7175 |                  _db = new Database(filePath);
       ^
error: unable to open database file
 statusCode: 500,
      fatal: false,
  unhandled: true,
 statusMessage: undefined,
       data: undefined,

      at open (unknown:1:1)
      at new Database (bun:sqlite:260:28)
      at getDB (/app/.output/server/index.mjs:7175:14)
      at prepare (/app/.output/server/index.mjs:7731:3)
      at /app/.output/server/index.mjs:7846:17
      at all (/app/.output/server/index.mjs:7844:14)
      at processTicksAndRejections (native:7:39)

7170 |          if (opts.name === ":memory:") {
7171 |                  _db = new Database(":memory:");
7172 |          } else {
7173 |                  const filePath = resolve$1(opts.cwd || ".", opts.path || `.data/${opts.name || "db"}.bun.sqlite`);
7174 |                  mkdirSync(dirname$1(filePath), { recursive: true });
7175 |                  _db = new Database(filePath);
       ^
SQLiteError: unable to open database file
      errno: 14,
 byteOffset: -1,
       code: "SQLITE_CANTOPEN"

      at open (unknown:1:1)
      at new Database (bun:sqlite:260:28)
      at getDB (/app/.output/server/index.mjs:7175:14)
      at prepare (/app/.output/server/index.mjs:7731:3)
      at /app/.output/server/index.mjs:7846:17
      at all (/app/.output/server/index.mjs:7844:14)
      at processTicksAndRejections (native:7:39)

[request error] [unhandled] [POST] http://localhost/__nuxt_content/help/query?v=v3.5.0--R4Jkm8iUOdTraAOZDik1Qabjbov03KYvkgl3N6Wk-xk
 7170 |                 if (opts.name === ":memory:") {
7171 |                  _db = new Database(":memory:");
7172 |          } else {
7173 |                  const filePath = resolve$1(opts.cwd || ".", opts.path || `.data/${opts.name || "db"}.bun.sqlite`);
7174 |                  mkdirSync(dirname$1(filePath), { recursive: true });
7175 |                  _db = new Database(filePath);
       ^
error: unable to open database file
 statusCode: 500,
      fatal: false,
  unhandled: true,
 statusMessage: undefined,
       data: undefined,

      at open (unknown:1:1)
      at new Database (bun:sqlite:260:28)
      at getDB (/app/.output/server/index.mjs:7175:14)
      at prepare (/app/.output/server/index.mjs:7731:3)
      at /app/.output/server/index.mjs:7846:17
      at all (/app/.output/server/index.mjs:7844:14)
      at processTicksAndRejections (native:7:39)

7170 |          if (opts.name === ":memory:") {
7171 |                  _db = new Database(":memory:");
7172 |          } else {
7173 |                  const filePath = resolve$1(opts.cwd || ".", opts.path || `.data/${opts.name || "db"}.bun.sqlite`);
7174 |                  mkdirSync(dirname$1(filePath), { recursive: true });
7175 |                  _db = new Database(filePath);
       ^
SQLiteError: unable to open database file
      errno: 14,
 byteOffset: -1,
       code: "SQLITE_CANTOPEN"

      at open (unknown:1:1)
      at new Database (bun:sqlite:260:28)
      at getDB (/app/.output/server/index.mjs:7175:14)
      at prepare (/app/.output/server/index.mjs:7731:3)
      at /app/.output/server/index.mjs:7846:17
      at all (/app/.output/server/index.mjs:7844:14)
      at processTicksAndRejections (native:7:39)

malformed-c avatar Dec 06 '25 11:12 malformed-c