{"record":{"id":"9ec376235e7abe62","repo":"tursodatabase/turso","slug":"expected-first-argument-to-be-a-function-9ec376","errorCode":null,"errorMessage":"Expected first argument to be a function","messagePattern":"Expected first argument to be a function","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"bindings/javascript/sync/packages/native/promise.ts","lineNumber":267,"sourceCode":"            isReadonly,\n            this.#remoteWriter,\n            () => this.pull(),\n        ) as any;\n    }\n\n    /**\n     * Returns a function that executes the given function in a transaction.\n     * When remoteWrites is enabled, the entire transaction goes to remote.\n     *\n     * @deprecated Use {@link transactionAsync} instead: this wrapper does\n     * not own the connection, so concurrent statements can interleave into\n     * the transaction's window.\n     */\n    override transaction<F extends (...args: any[]) => Promise<any>>(\n        fn: F,\n    ): TransactionFunction<F> {\n        if (typeof fn !== \"function\")\n            throw new TypeError(\"Expected first argument to be a function\");\n\n        if (!this.#remoteWriter) {\n            return super.transaction(fn);\n        }\n\n        const db = this;\n        const remoteWriter = this.#remoteWriter;\n        const wrapTxn = (mode: string) => {\n            return async (...bindParameters: any[]) => {\n                await remoteWriter.beginTransaction(mode);\n                try {\n                    const result = await fn(...bindParameters);\n                    await remoteWriter.commitTransaction();\n                    await db.pull();\n                    return result;\n                } catch (err) {\n                    await remoteWriter.rollbackTransaction();\n                    throw err;","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/javascript/sync/packages/native/promise.ts#L249-L285","documentation":"transaction() builds a wrapper that runs your callback between BEGIN and COMMIT, so the first argument must be a function; anything else throws this TypeError immediately. Note the source marks this wrapper deprecated precisely because it does not own the connection — concurrent statements can interleave into the transaction window — but the argument check applies regardless. The thrown error names the exact expectation.","triggerScenarios":"db.transaction('SELECT ...') passing SQL text instead of a callback (pattern from other drivers); db.transaction() with undefined because the callback variable was misspelled or hoisted incorrectly; passing an options object or an array of statements.","commonSituations":"Migrating from sqlite3/better-sqlite3 APIs or raw SQL-string transaction helpers; passing a method reference that lost its binding and became undefined; refactors renaming the callback parameter.","solutions":["Pass a function: db.transaction(async () => { ... }) and call the returned wrapper.","Check typeof fn === 'function' at the call boundary in JavaScript code.","Rely on TypeScript's generic constraint F extends (...args: any[]) => Promise<any> to catch this at compile time."],"exampleFix":"// before\nconst runTxn = db.transaction(userCallbackOrSql); // may be a string/undefined\n\n// after\nif (typeof userCallbackOrSql !== 'function') {\n  throw new TypeError('transaction() requires a callback function');\n}\nconst runTxn = db.transaction(userCallbackOrSql);","handlingStrategy":"type-guard","validationCode":"if (typeof fn !== 'function') {\n  throw new TypeError('transaction() requires a callback function');\n}\nconst runTxn = db.transaction(fn);","typeGuard":"const isTxnCallback = (f: unknown): f is (...args: any[]) => Promise<any> =>\n  typeof f === 'function';","tryCatchPattern":null,"preventionTips":["Rely on TypeScript so the generic constraint catches non-functions at compile time.","Never pass raw SQL strings — this API takes a callback, unlike some other drivers.","Check method references are bound before handing them to transaction()."],"tags":["transaction","type-validation","javascript"],"backgroundTag":"invalid-argument-type","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}