{"slug": "3-bugs-i-fixed-before-shipping-my-whatsapp-ai-receptionist", "title": "3 Bugs I Fixed Before Shipping My WhatsApp AI Receptionist", "summary": "Full-stack developer Sajib fixed three bugs in the knowledge pipeline (CSV/PDF/URL → chunks → Postgres) of a WhatsApp AI receptionist before shipping it in v0.5.0. The bugs included a deduplication flaw that silently discarded unchanged chunks and deleted them when the old version was replaced, a check-then-act race letting two workers claim the same pending source, and a URL-fetch vulnerability exposing localhost, internal services, and cloud metadata via redirects. The fixes—transactional version replacement, atomic claim via a conditional UPDATE with RETURNING, and URL-fetch safeguards capping responses at 5 MB—shipped with 30 tests using Node's built-in test runner.", "body_md": "My WhatsApp AI receptionist answered pricing questions, booked appointments, and handed off to a human.\n\nThe demo worked. Then a production review exposed three bugs in its knowledge pipeline: **CSV/PDF/URL → chunks → Postgres.**\n\nDeduplication compared incoming chunks against the previous version. Unchanged chunks were discarded as duplicates—then deleted when the old version was replaced.\n\nA 10% update left just 10% of the knowledge. No error. Just missing answers.\n\n**Fix:** Identify the previous version before deduping, exclude its chunks from the comparison, and replace it in one transaction. Add a regression test.\n\nA `SELECT` followed by an `UPDATE` let two workers pick the same pending source.\n\n**Fix:** Claim it atomically:\n\n```\nUPDATE knowledge_sources\nSET status = 'processing'\nWHERE id = $1\n  AND status = 'pending'\nRETURNING *;\n```\n\nNo returned row means no claim. That worker skips ingestion.\n\nA submitted URL could send the server to localhost, internal services, or cloud metadata—including through redirects.\n\n**Fix:** Add URL-fetch safeguards: allow HTTP(S) only, check resolved IPs for internal destinations, revalidate every redirect, and cap responses at 5 MB.\n\nThese fixes shipped in **v0.5.0**, with **30 tests** using Node’s built-in runner.\n\nA working conversation is only part of the test. Re-uploads, competing workers, and untrusted URLs deserve their own.\n\n**Which of these has caught you before? My bet: the check-then-act race.**\n\n*— Sajib, full-stack developer from Dhaka · [sajib.dev.cv](https://sajib.dev.cv)*", "url": "https://wpnews.pro/news/3-bugs-i-fixed-before-shipping-my-whatsapp-ai-receptionist", "canonical_source": "https://dev.to/sajeeb_ahmed/3-bugs-i-fixed-before-shipping-my-whatsapp-ai-receptionist-175m", "published_at": "2026-10-20 06:12:37+00:00", "updated_at": "2026-10-20 06:17:17.501605+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "mlops", "developer-tools"], "entities": ["Sajib", "WhatsApp", "Postgres", "Node.js"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/3-bugs-i-fixed-before-shipping-my-whatsapp-ai-receptionist", "markdown": "https://wpnews.pro/news/3-bugs-i-fixed-before-shipping-my-whatsapp-ai-receptionist.md", "text": "https://wpnews.pro/news/3-bugs-i-fixed-before-shipping-my-whatsapp-ai-receptionist.txt", "jsonld": "https://wpnews.pro/news/3-bugs-i-fixed-before-shipping-my-whatsapp-ai-receptionist.jsonld"}}