Convex ESLint Compliance Write all Convex functions to pass @convex-dev/eslint-plugin. These rules prevent common bugs, security issues, and ensure code quality. Documentation Sources https://docs.convex.dev/eslint https://www.npmjs.com/package/@convex-dev/eslint-plugin Setup Install the plugin: npm i @convex-dev/eslint-plugin --save-dev Configure eslint.config.js : import { defineConfig } from "eslint/config" ; import convexPlugin from "@convex-dev/eslint-plugin" ; export default defineConfig ( [ ... convexPlugin . configs . recommended ] ) ; Rules 1. no-old-registered-function-syntax Always use object syntax with a handler property. // Correct export const list = query ( { args : { } , handler : async ( ctx ) => { return await ctx . db . query ( "messages" ) . collect ( ) ; } , } ) ; // Wrong - bare function syntax export const list = query ( async ( ctx ) => { return await ctx . db . query ( "messages" ) . collect ( ) ; } ) ; 2. require-argument-validators Always include args object, even when empty. // Correct - with arguments export const get = query ( { args : { id : v . id ( "messages" ) } , handler : async ( ctx , { id } ) => { return await ctx . db . get ( "messages" , id ) ; } , } ) ; // Correct - no arguments export const listAll = query ( { args : { } , handler : async ( ctx ) => { return await ctx . db . query ( "messages" ) . collect ( ) ; } , } ) ; // Wrong - missing args export const get = query ( { handler : async ( ctx , { id } : { id : Id < "messages"
} ) => { return await ctx . db . get ( "messages" , id ) ; } , } ) ; 3. explicit-table-ids Use explicit table names in all database operations (Convex 1.31.0+). // Correct const message = await ctx . db . get ( "messages" , messageId ) ; await ctx . db . patch ( "messages" , messageId , { text : "updated" } ) ; await ctx . db . replace ( "messages" , messageId , { text : "replaced" , author : "Alice" , } ) ; await ctx . db . delete ( "messages" , messageId ) ; // Wrong - implicit table from ID type const message = await ctx . db . get ( messageId ) ; await ctx . db . patch ( messageId , { text : "updated" } ) ; await ctx . db . replace ( messageId , { text : "replaced" , author : "Alice" } ) ; await ctx . db . delete ( messageId ) ; Migration codemod available: npx @convex-dev/codemod@latest explicit-ids 4. import-wrong-runtime Never import Node.js runtime files into Convex runtime files. // convex/queries.ts (no "use node" directive) // Correct - importing from Convex runtime file import { helper } from "./utils" ; // utils.ts has no "use node" // Wrong - importing from Node runtime file import { nodeHelper } from "./nodeUtils" ; // nodeUtils.ts has "use node" Best Practices Run ESLint before committing: npx eslint convex/ Use auto-fix for quick migrations: npx eslint convex/ --fix Add to CI pipeline to catch violations early Configure your editor for real-time feedback Quick Reference Rule What it enforces no-old-registered-function-syntax Object syntax with handler require-argument-validators args: {} on all functions explicit-table-ids Table name in db operations import-wrong-runtime No Node imports in Convex runtime References ESLint Plugin Docs Explicit IDs Announcement