#15840·chatwoot

Facebook Messenger creates John Doe contacts when Graph returns name instead of first_name/last_name

Author: nmgitadminCreated Sep 16, 2026Updated Sep 17, 2026
LabelsBugchannel/facebook

Describe the bug

Facebook Messenger contacts can be created as John Doe even when the Graph API successfully returns the sender's real name. A related case appends a fabricated Doe to a valid single-part name.

Our app's Business Asset User Profile Access has been approved/enabled. Using the affected inbox's Page access token and the exact ContactInbox#source_id, the same Koala::Facebook::API#get_object call used by Chatwoot returns a valid profile. However, Chatwoot ignores its name field and substitutes missing first_name / last_name with John / Doe.

Runtime verified on v4.16.2. The same relevant logic is present in the v4.17.0 source; we have not deployed or runtime-tested v4.17.0.

To Reproduce

  1. Connect a Facebook Page inbox with working profile access.
  2. Receive a message/event that creates a new contact for a sender whose profile response contains name and id, but does not contain first_name or last_name.
  3. Observe that the contact is saved as John Doe.
  4. Query the same source ID using the same Page access token. A valid name is returned.

Observed response shapes are shown below with names and IDs replaced by synthetic values:

json
{"name": "Sample Customer", "id": "REDACTED"}

Expected contact name: Sample Customer. Actual: John Doe.

We also observed this response shape for a different contact:

json
{"first_name": "SingleName", "profile_pic": "REDACTED", "id": "REDACTED"}

Expected: SingleName. Actual: SingleName Doe. An explicit profile query for this contact confirmed that its name is the same single-part name and that no last_name is returned.

The mapping can be isolated in a Rails console without accessing Meta or writing any records:

ruby
builder = Messages::Facebook::MessageBuilder.allocate
builder.instance_variable_set(:@inbox, Struct.new(:account_id).new(1))

builder.send(:process_contact_params_result,
             { 'id' => 'example', 'name' => 'Sample Customer' })[:name]
# Current mapping: "John Doe"

builder.send(:process_contact_params_result,
             { 'id' => 'example', 'first_name' => 'SingleName' })[:name]
# Current mapping: "SingleName Doe"

Expected behavior

  • Use a nonblank full name when provided by Meta.
  • Otherwise build the display name from the available nonblank first/last name components, without inventing a missing component.
  • Use an unknown-contact fallback only when no usable name is available.
  • Provide a safe way to refresh previously generated placeholder names once valid profile data is available, while preserving names edited by agents.

Environment

Self-hosted Kubernetes; unmodified upstream chatwoot/chatwoot:v4.16.2 image, served through a registry mirror. Facebook Page / Messenger channel.

Cloud Provider

AWS.

Platform

Browser. The failure is in the server-side contact-name mapping.

Operating system

Linux containers; Windows client.

Browser and version

Chrome; exact browser version not recorded.

Docker (if applicable)

Container image tag: v4.16.2. Kubernetes deployment; Docker/Compose version output is not applicable to this report.

Additional context

Source references in v4.17.0:

  • Name mapping and profile request: process_contact_params_result ignores name, and contact_params uses get_object(@sender_id).
  • Existing contact-inbox early return: existing mappings return before the newly fetched contact attributes are applied. This explains why enabling profile access later does not itself repair stored placeholders.

Observed impact on 2026-09-16:

  • One newly connected inbox had 98 contacts named John Doe out of 126 contacts at the first audit.
  • A subsequent one-time data repair recovered 108 verified names, including one partial placeholder (SingleName Doe).
  • All 108 updates were verified, but 10 more John Doe contacts had been created after the repair snapshot. Therefore this affects newly created contacts as well as historical data.
  • No application-code or image patch was applied.

Related earlier reports: #5567 and #9758. This report adds successful Graph responses and the specific name-mapping behavior, rather than assuming every John Doe contact is caused by missing permissions.

Names, source IDs, customer messages, domains, and credentials have been omitted or replaced. We would prefer an upstream fix in the official image, including regression coverage for full-name-only and single-part-name profiles.