// Prisma error codes all match P followed by 4 digits const PRISMA_CODE_RE = /^P\d{4}$/; /** * Returns a client-safe error message. * Prisma errors and connection errors can expose table names, column names, * DB hostnames and ports — replace those with generic messages. * Intentional application errors (thrown with `new Error('...')` in controllers) * are passed through unchanged. */ function safeErrorMessage(err) { if (!err) return 'An unexpected error occurred.'; const code = String(err.code || ''); // Prisma client / query engine errors if (PRISMA_CODE_RE.test(code)) { switch (code) { case 'P2002': return 'A record with that value already exists.'; case 'P2025': return 'Record not found.'; case 'P2003': return 'Operation failed due to a related record constraint.'; case 'P2016': return 'Required record not found.'; default: return 'A database error occurred. Please try again.'; } } const msg = String(err.message || ''); // DB connection / network errors leak hostnames and ports if ( msg.includes("Can't reach database") || msg.includes('ECONNREFUSED') || msg.includes('ETIMEDOUT') || msg.includes('Connection refused') || msg.includes('database server') ) { return 'A database connection error occurred. Please try again later.'; } return msg || 'An unexpected error occurred.'; } module.exports = { safeErrorMessage };