chatwoot/chatwoot · error · Voice::CallErrors::CallFailed

Failed to initiate call

Error message

Failed to initiate call

What it means

After initiate_call, the WhatsApp Cloud provider inspects a non-success response: if Meta's error code equals Voice::CallErrors::NO_CALL_PERMISSION_CODE (138006) it raises Voice::CallErrors::NoCallPermission, otherwise Voice::CallErrors::CallFailed, with the first non-blank of error_user_msg / message / error_user_title or the fallback 'Failed to initiate call'. The status and body are logged as [WHATSAPP CALL] for diagnosis.

Source

Thrown at enterprise/app/services/enterprise/whatsapp/providers/whatsapp_cloud_service.rb:111

  def initiate_call_body(to_phone_number, sdp_offer)
    {
      messaging_product: 'whatsapp', to: to_phone_number, action: 'connect',
      session: { sdp: sdp_offer, sdp_type: 'offer' }
    }.to_json
  end

  def process_initiate_call_response(response)
    return response.parsed_response if response.success?

    Rails.logger.error "[WHATSAPP CALL] initiate_call failed: status=#{response.code} body=#{response.body}"
    parsed = response.parsed_response.is_a?(Hash) ? response.parsed_response : {}
    error = parsed['error'].is_a?(Hash) ? parsed['error'] : {}
    error_code = error['code']
    error_msg = meta_error_message(error, 'Failed to initiate call')

    raise Voice::CallErrors::NoCallPermission, error_msg if error_code == Voice::CallErrors::NO_CALL_PERMISSION_CODE

    raise Voice::CallErrors::CallFailed, error_msg
  end

  # Meta often returns a blank error_user_msg (e.g. code 131044 business-eligibility);
  # an empty string is truthy, so `||` would surface it. Prefer the first non-blank field.
  def meta_error_message(error, default)
    error['error_user_msg'].presence || error['message'].presence || error['error_user_title'].presence || default
  end
end

View on GitHub (pinned to ed230f9bc0)

Solutions

  1. Confirm WhatsApp Cloud Calling is enabled/eligible for the phone number in Meta Business Manager
  2. For NoCallPermission (code 138006), have the contact accept WhatsApp call permissions, then retry
  3. Verify the channel's access token is valid and has calling permissions; re-issue if rotated
  4. Read the [WHATSAPP CALL] log line (status + body) and check Meta system status for outages

Example fix

# before
provider_service.initiate_call(call.provider_call_id, sdp_offer)
# raises Voice::CallErrors::CallFailed: Failed to initiate call

# after
begin
  provider_service.initiate_call(call.provider_call_id, sdp_offer)
rescue Voice::CallErrors::NoCallPermission
  # surface 'contact has not granted call permission' in UI, do not retry immediately
rescue Voice::CallErrors::CallFailed => e
  Rails.logger.error("initiate_call hard failure: #{e.message}")
end
Defensive patterns

Strategy: try-catch

Try / catch

begin
  provider_service.initiate_call(call_id, sdp_offer)
rescue Voice::CallErrors::NoCallPermission
  # 138006: contact must grant call permission — surface instruction, do not auto-retry
rescue Voice::CallErrors::CallFailed => e
  # eligibility/token/Meta failure — log e.message (already prefers error_user_msg) and alert
end

Prevention

When it happens

Trigger: WhatsApp voice call initiation where the Cloud API returns non-2xx: WABA/number lacks Cloud Calling eligibility (e.g. code 131044 with a blank error_user_msg, which is why presence-aware selection is used), an invalid/expired access token, or a Meta 5xx.

Common situations: New WhatsApp Business Account without voice access; contact has not granted call permission (138006); rotated or expired permanent token; Meta platform incident.

Related errors


AI-assisted analysis of chatwoot/chatwoot@ed230f9bc0 (2026-08-21). Data as JSON: /api/errors/635177e02fabf409. Report an issue: GitHub.