Facebook Messenger creates John Doe contacts when Graph returns name instead of first_name/last_name
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
- Connect a Facebook Page inbox with working profile access.
- Receive a message/event that creates a new contact for a sender whose profile response contains
nameandid, but does not containfirst_nameorlast_name. - Observe that the contact is saved as
John Doe. - 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:
{"name": "Sample Customer", "id": "REDACTED"}Expected contact name: Sample Customer. Actual: John Doe.
We also observed this response shape for a different contact:
{"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:
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
namewhen 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_resultignoresname, andcontact_paramsusesget_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.
Source: chatwoot/chatwoot