Please excuse our look. We're just getting started here.

Want to learn more about Twilio Forums? Check out our FAQ page here.

@twilio/voice-sdk doesn't receive incoming calls.

const device = new Device(voiceToken, {
  logLevel: 'debug',
});

await device.register();

device.on('incoming', (call: Call) => {
  handleCallStateChange(call);
  // Or some other stuff
});

I'm doing something like the above to work with Twilio Voice. I can make outgoing calls from the browser, but I don't receive any incoming calls. It just immediately hangs up and the incoming event is never fired.

I don't see anything in the logs either. I can't revert back to the old twilio-client because that package seems to be incompatible with a lot of other things.

I'm using:

"@twilio/voice-sdk": "^2.0.1",
"twilio": "^3.70.0",
"twilio-video": "^2.18.0",

Any help on what's going on here would be appreicated.

Tagged:

Answers

  • Hi @ethang , Twilio Developer Educator here.

    Can you verify that your phone number is configured to point to the TwiML App you're using for the SDK? (I don't think this is the problem, because you're not hearing "Sorry. An application error has occurred." but it's good to check.)

    And then can you possibly show me the endpoint you have for serving TwiML back to Twilio for incoming/outgoing calls?

    Are you able to verify that that endpoint is being hit when you dial your Twilio number

    Also, can you verify that the endpoint is telling Twilio to <Dial> your local device (via the identity you passed to the device's Access Token) for incoming calls?

    This is where I'd start looking for issues. If you're not seeing any Call logs (in the Twilio Console), that makes me think there's an issue with your endpoint and/or the TwiML being sent back to Twilio. If you are seeing Call Logs, please post what errors (if any) you see.

    Thanks, and hopefully we can get to the bottom of this issue!

  • ethang
    ethang
    edited January 6

    I'm using libraries for tokening, not REST endpoints. The voice token comes from twilio/lib/jwt/ClientCapability. (twilio 3.70.0 package)

    createClient() {
      this.client = twilio(
        process.env.TWILIO_ACCOUNT_SID,
        process.env.TWILIO_AUTH_TOKEN
      );
    }
    
    getVoiceToken(username: string, domain: string): string {
      this.createClient();
      const identity = `${username}${domain}`.toLowerCase();
      const appSid = process.env.TWILIO_APP_SID;
      const accountSid = process.env.TWILIO_ACCOUNT_SID;
      const authToken = process.env.TWILIO_AUTH_TOKEN;
    
      const capability = new ClientCapability({
        accountSid,
        authToken,
        ttl: 14_400,
      });
      capability.addScope(new ClientCapability.IncomingClientScope(identity));
      capability.addScope(
        new ClientCapability.OutgoingClientScope({ applicationSid: appSid })
      );
    
      return capability.toJwt();
    }
    

    With the token, I just initialize the device and connect with it.

    I'm working on figuring out the maze of apps we have on Twilio, because I don't really understand why we have so many SID's and why, suddenly, when I've been using the same one for voice, I now I have issues.

    Or to be a little more clear. I don't use TwiML. (Didn't really know what that was, or REST.) I create a client, generate a token, and listen for events.

  • Ah, okay, I think we've found the problem.

    The Voice JS SDK v2 and above needs Access Tokens, which are a little different from Capability Tokens. Most importantly in your case, it contains an "identity" property that ties a browser device to a specific identity. Here's an example from the Voice JS SDK Node Quickstart.

    If you're upgrading from v1 to v2, there are a few other pieces that may trip you up. Here's the Migration Guide to show you what has changed and what you may need to update.

    To get you oriented with the Voice JavaScript SDK, I'd recommend you start with this page:

    https://www.twilio.com/docs/voice/sdks/javascript

    And then walk through one of the quickstarts (Node.js, Python, etc.) to orient you on how the pieces fit together.

    The JavaScript SDK is made up of a client side app (HTML/JS/CSS with the JS SDK), a backend (that serves TwiML and sometimes AccessTokens), a TwiML App (which is used to configure your phone number and is critical for using the JS SDK).

    Twilio Voice requires the use of TwiML ... it's the way Twilio gets instructions on what number or client to dial, what text to speech a caller should hear, etc.

  • I don't understand the tie between voice-sdk and TwiML. TwiML isn't something we've ever used in this app. In production, it's using twilio-client and ClientCapabilities. From there it's simply just device.connect() and device.on('incoming') as the documentation suggests.

    I've been through the migration guide, that's exactly what led to the code in my original post. However, it did not mention a change in Voice tokening. But I changed that yesterday to look like this:

    createClient() {
      this.client = twilio(
        process.env.TWILIO_ACCOUNT_SID,
        process.env.TWILIO_AUTH_TOKEN
      );
    }
    
    getVoiceToken(username: string, domain: string): string {
      this.createClient();
      const identity = `${username}${domain}`.toLowerCase();
      const twilioAccountSid = process.env.TWILIO_ACCOUNT_SID;
      const twilioApiKey = process.env.TWILIO_API_KEY_SID;
      const twilioApiSecret = process.env.TWILIO_API_KEY_SECRET;
      const outgoingApplicationSid = process.env.TWILIO_APP_SID;
    
      const voiceGrant = new VoiceGrant({
        incomingAllow: true,
        outgoingApplicationSid,
      });
    
      const token = new AccessToken(
        twilioAccountSid,
        twilioApiKey,
        twilioApiSecret,
        { identity }
      );
      token.addGrant(voiceGrant);
    
      return token.toJwt();
    }
    

    With this, I get the same results. I can create the device and register it. Outgoing calls are possible, incoming calls don't go through. It's just an immediate hang-up.

  • ethang
    ethang
    edited January 7

    Ok, so I'm coming into an app that hasn't really been maintained and is currently bricked.

    So I see now our TwiML server, not something I've worked with before.

    My big question here is. Are there any other breaking changes between these packages that could affect TWiML, tokening, or the client?

    What we have in production:

    twilio: 3.39.3

    twilio-client 1.12.5

    What I'm working with now:

    @twilio/voice-sdk: 2.0.1

    twilio: 3.70.0


    Out TwiML server is using:

    twilio: 3.49.0

  • bdelvalle
    bdelvalle ✭✭
    edited January 7

    If you are able to make outgoing calls with the SDK, TwiML is being used somewhere.



    Let's look at how the SDK works. (More information on https://www.twilio.com/docs/voice/sdks/javascript)

    Here's an image that may help... (This image really only displays outgoing calls, but the relationship between the SDK and TwiML is what we want to focus on.)


    For outgoing calls with the SDK, the SDK looks to the TwiML App that is associated with the Access Token (the outgoing application SID in the token). (The TwiML App is just a collection of URLs that tells Twilio where to look for instructions ... and those instructions are TwiML.)

    So, for outgoing calls:

    Browser Device -> TwiML App -> Some URL that will return TwiML -> Twilio executes the TwiML instructions (likely in your case to be just <Dial> the number sent from the browser device).


    For incoming calls, it's a bit different:

    You have a phone number that you bought from Twilio. When that phone number is called, Twilio will look to the phone number's configuration for TwiML instructions.

    How does Twilio know which browser device to dial? We need to provide it with TwiML instructions that tell it to <Dial> the specific identity we included in the browser device's Access Token. (It would look something like <Dial><Client>ethang</Client></Dial>). This is done by pointing Twilio to that same TwiML App we mentioned above.

    The quickstart repos have directions for the setup, as well as sample endpoints that handle incoming and outgoing calls by serving TwiML to Twilio.


    Below, I'm going to list the steps to find out how your Twilio phone number is configured, and hopefully track down where the TwiML is coming from for outgoing and incoming calls.

    1. Go to your Twilio Console (twilio.com/console) and log in
    2. Find your phone number. In the left navigation pane, go to Phone Numbers -> Manage -> Active Numbers
    3. Find the phone number you've been calling to test the SDK and click on it.
    4. On the phone number's page, scroll down to the Voice & Fax section and find "Configure with" and "When a call comes in"

    Can you tell me what you see there?

    This is where Twilio will look for TwiML instructions once a call comes in to that number. It could be a TwiML Bin, a Webhook, etc. The JavaScript SDK needs the phone number to be configured with a TwiML App in order to send outgoing calls (and since you have outgoing calls working, that tells me there is a TwiML App associated with the app.)

    If you see that it is configured with a TwiML App, let's look at it:

    1. In your Twilio Console's left navigation, click on Voice -> Manage -> TwiML apps.
    2. Find the TwiML App that your phone number was configured with and click on it
    3. On the TwiML App's page, you should see Voice Configuration, and that is where Twilio is sending a webhook (an HTTP request) looking for TwiML instructions.

    If you got to this point, can you also describe what you're seeing here?

  • Ah, I just saw that you replied while I was drafting my comment.


    Can you tell me more about what you mean by "bricked"? Are you seeing any error messages in the browser console or the Twilio Console?

  • Another thing to check is the Call logs and Error logs in the Twilio Console.

    In the left navigation pane, up at the top, click on Monitor, then Logs -> Errors -> Error logs. Check to see if you see any errors related to these test calls you've been making.

    Also, you can look at Logs -> Calls and you can see what the TwiML looks like that Twilio received for these incoming calls.

  • ethang
    ethang
    edited January 7

    I'm able to look at the logs today. I can see the incoming call from my mobile number to my twilio number succeeds. But the next call that goes from my mobile to my client:{identity} times out with a no answer.

    Which only brings me back to the original issue. This method isn't catching incoming calls.

    device.on('incoming', (call: Call) => {
      handleCallStateChange(call);
      // Or some other stuff
    });
    

    I've put the entire device object that I can make outbound calls with (with tokens and gateway removed) in a pastebin here:

    https://pastebin.com/hyDfeCYx

    I also simplified the client code to have all of this in one spot for testing. It's using the following:

    useEffect(() => {
      const setup = async (): Promise<void> => {
        if (data?.domainUser.Twilio?.voiceToken) {
          const device = new Device(data.domainUser.Twilio.voiceToken);
          await device.register();
          device.on('incoming', (call_: Call) => {
            if (
              // eslint-disable-next-line no-alert
              window.confirm(
                `Incoming Call from ${call_.parameters.From}. Answer?`
              )
            ) {
              call_.accept();
            } else {
              call_.reject();
            }
          });
          setDevice(device);
          console.log(device);
        }
      };
    
      setup().catch((error: Error) => {
        console.error(error);
      });
    }, [data?.domainUser.Twilio?.voiceToken]);
    


  • bdelvalle
    bdelvalle ✭✭
    edited January 7

    Thanks for all this information. I'm still suspecting the issue is with the TwiML that Twilio is trying to execute. I think the reason your incoming event listener isn't catching a call is because there isn't actually a call being dialed toward your browser device. Let's check the TwiML for the call.

    Under Monitor in the left navigation pane go to Logs -> Calls and click on the CallSID for one of your calls to your Twilio number.

    Can you tell me if you see any Errors & Warnings on that page?

    If not, can you go to the Request Inspector section and look under Response -> Body?

    It should be some TwiML that looks like this:

    <?xml version="1.0" encoding="UTF-8"?>
    <Response>
        <Dial callerId="+15557777777">
            <Client>ethang</Client>
        </Dial>
    </Response>
    


    Also, would you share the code that's in the the server-side endpoint that is supposed to handle incoming calls to your Twilio number?

  • ethang
    ethang
    edited January 8

    Well, sorry for not having all information. I think the major issue for me here is I've got code I can't debug. So I can't trace the problem, only guess. ie. I don't have access or a way to really look at the TwiML server.

    Yes, there are errors.

    On the call from my mobile to my Twilio number I get a 502 timeout to {api}/inboundstatuscallback but a 200 success to {api}/inboundcall

    On the call from my mobile to client:{identity} I just get two 502 timeouts to {api}/inboundstatuscallback. I am told it's normal for inboundstatuscallback to timeout on everything.

    If everything seems ok to you up to this point. ie With the way I'm creating tokens, and dealing with the client I'm at a place where I can't give you much and I can't do much. Might have to let this one stew for a bit until someone gets mad enough to get me in the game so I can fix it.

  • Fuck I’m going through the same issue but on iOS. I’m using the latest SDK 6.3.1.


    i was able to have outgoing call easily

    outgoing/incoming sms too


    but incoming call. No way


    its quite similar to this issue.

    i receive the phone call to my Twilio number.

    then redirect to dial my client with nodejs/TwiML

    but then nothing happens, I can see the 2nd call in the logs but no notification arrive on my debug phone (not simulator).


    the worst is that I had done a poc last year that worked in one day. But now the same code isn’t working anymore. Maybe I messed the APN/voip credentials but no error is showing in the error logs

  • @daavidaviid I'm sorry to hear your having this issue. Would you like me to connect you with our Voice support team? If so, please DM me your full name, email address and timezone.

    Cheers!

If this is an emergency, please contact Twilio Support. This is not an official Support channel. https://support.twilio.com/
Have an urgent question?
Please contact Twilio Support. This is not an official Support channel.
Contact Support