{"record":{"id":"58d4619fd1845ce1","repo":"tursodatabase/turso","slug":"client-closed","errorCode":"CLIENT_CLOSED","errorMessage":"Client is closed","messagePattern":"Client is closed","errorType":"exception","errorClass":"LibsqlError","httpStatus":null,"severity":"error","filePath":"serverless/javascript/src/compat.ts","lineNumber":307,"sourceCode":"    if (options != null && typeof options === \"object\") {\n      return {\n        mode: options.mode,\n        raw: options.raw === true,\n      };\n    }\n    return {\n      mode: options,\n      raw: false,\n    };\n  }\n\n  async execute(stmt: InStatement): Promise<ResultSet>;\n  async execute(sql: string, args?: InArgs): Promise<ResultSet>;\n  async execute(stmtOrSql: InStatement | string, args?: InArgs): Promise<ResultSet> {\n    await this.execLock.acquire();\n    try {\n      if (this._closed) {\n        throw new LibsqlError(\"Client is closed\", \"CLIENT_CLOSED\");\n      }\n\n      let normalizedStmt: { sql: string; args: any[] };\n\n      if (typeof stmtOrSql === 'string') {\n        const normalizedArgs = args ? (Array.isArray(args) ? args : Object.values(args)) : [];\n        normalizedStmt = { sql: stmtOrSql, args: normalizedArgs };\n      } else {\n        normalizedStmt = this.normalizeStatement(stmtOrSql);\n      }\n\n      const result = await this.session.execute(normalizedStmt.sql, normalizedStmt.args, this._defaultSafeIntegers);\n      return this.convertResult(result);\n    } catch (error: any) {\n      if (error instanceof LibsqlError) {\n        throw error;\n      }\n      throw mapDatabaseError(error, \"EXECUTE_ERROR\");","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/serverless/javascript/src/compat.ts#L289-L325","documentation":"execute() checks the _closed flag under the client's exec lock and throws LibsqlError code CLIENT_CLOSED if the client was closed earlier. The compatibility client is not reconnectable: after close() every execute (and batch/transaction) on the same instance fails with this error.","triggerScenarios":"client.execute(sql) after client.close() ran - typically a shared module-level client closed by an error handler, a shutdown hook, or hot-reload cleanup, while later requests still reference it.","commonSituations":"Serverless handler closes the client in a finally block but the module-level singleton is reused by the next invocation; test teardown closing the client then assertions still running queries; close-on-error followed by a retry that reuses the same instance.","solutions":["Recreate the client: call createClient(config) again to get a fresh, open instance","Check the client.closed getter before issuing queries on shared instances","Scope close() to true app shutdown only; in serverless runtimes keep the client alive across invocations instead of closing per request","Audit finally blocks and error handlers for premature close() calls"],"exampleFix":"// before\nfinally { client.close(); }\n// next request:\nawait client.execute('SELECT 1'); // throws CLIENT_CLOSED\n\n// after - lazy reusable client, never closed per request\nlet client = createClient(config);\nexport async function query(sql: string) {\n  if (client.closed) client = createClient(config);\n  return client.execute(sql);\n}","handlingStrategy":"type-guard","validationCode":"if (client.closed) {\n  client = createClient(config);\n}\nconst rs = await client.execute(sql);","typeGuard":"function isOpen(client: Client): boolean {\n  return !client.closed;\n}","tryCatchPattern":"catch (e) { if (e instanceof LibsqlError && e.code === 'CLIENT_CLOSED') { client = createClient(config); return client.execute(sql); } throw e; }","preventionTips":["Close the client only at process/module teardown, never per request","Keep serverless clients module-scoped and warm across invocations","Audit finally blocks and error handlers for premature close() calls"],"tags":["serverless","client-lifecycle","use-after-close","libsql-compat"],"backgroundTag":"client-used-after-close","analyzedSha":"6c7252267988c76e632af00a671e4b9788dfae13","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}