Merge contact shows 404 for some contacts that open on the profile

Objective

  • Let staff open the Merge contact flow for any contact they can view on the profile, so duplicates can be consolidated without a dead-end 404.
  • Show a clear error when merge truly cannot load (missing contact, permissions), instead of a generic 404 that looks like the contact does not exist.

Background

  • In production, some contacts show a blank page with 404 in the browser tab when clicking Merge contact from the profile or contacts list. Other contacts merge normally.
  • Example contact (profile loads; merge fails): Contact profile → merge path: https://www.attik.ai/contacts/6a0c58c408bc100679748727/merge
  • Production routes www.attik.ai/contacts/* to the tools app via host rewrite in attik-frontend/next.config.js (destination: "/tools/:path*").
  • Likely cause (code review): The contact profile and merge pages both call GET contact/:id, but only the merge page validates the response with strict Zod (ContactWithBusinessPopulatedSchema) and calls notFound() on any failure—including validation errors. The profile page intentionally skips Zod (legacy/import field shapes). Legacy or imported contacts can therefore load on the profile but 404 on merge.
  • Confirmation step for QA: On a failing contact, DevTools → Network → GET contact/<id> on merge load. If status is 200 but the page is still 404, the failure is schema validation, not a missing contact.

Scope

Frontend

  • Merge page load: attik-frontend/src/app/tools/contacts/[contact_id]/merge/page.tsx — fetches contact/${contact_id} with ContactWithBusinessPopulatedSchema; catchnotFound() (Next.js 404).
  • Profile page (works today): attik-frontend/src/app/tools/contacts/[contact_id]/page.tsx — same API call without Zod (comment notes skipped validation for volume metrics / legacy values).
  • Schema: attik-frontend/src/util/types/serverTypeCollection/contact.ts — strict fields that may fail on older rows include tags (required array), preferredContactMethod, emailStatus, smsStatus, active, createdAt, updatedAt, ccEmails refine, populated _contactBusinessId.
  • Entry points: ContactDetailsSection.tsx (Merge button, disabled when isDeleted), ContactActions.tsx (list merge action).
  • Error UI exists but not used for validation failures: merge/error.tsx (only for thrown errors in client tree, not server notFound()).
  • Decision needed: Align merge initial load with profile (lenient parse / safeParse + defaults), and/or relax/normalize schema for legacy contacts. Do not map validation failures to notFound().

Backend

  • attik-backend/src/routes/contact.tsGET /:id via getSingleItem returns contact by Mongo id (404 only if doc missing); does not filter isDeleted on GET. Merge submit is POST /:id/merge (404 for missing secondary; 400 for deleted/already-merged)—out of scope for the page-load 404 unless investigation shows API 404 on GET for these ids.

Out of scope (unless investigation proves otherwise)

  • Merge submit logic and inspection/quote transfer (already implemented on POST /:id/merge).
  • Contacts that are soft-deleted (isDeleted)—Merge is already disabled on the profile for those.

References

Please authenticate to join the conversation.

Upvoters
Status

Planned

Board
🏠

Main App

Date

12 days ago

Author

Linear

Subscribe to post

Get notified by email when there are changes.