Summary
ConversationRelay serializes four attributes in all-lowercase, but the ConversationRelay TwiML docs document them in camelCase. XML attributes are case-sensitive, so these are silently ignored by the TwiML parser — the setting appears to apply but has no effect, with no error surfaced.
Affected attributes
src/main/java/com/twilio/twiml/voice/ConversationRelay.java:
| Line |
Emitted |
Documented |
| 165 |
backgroundnoisereduction |
backgroundNoiseReduction |
| 168 |
speechtimeout |
speechTimeout |
| 171 |
deepgramsmartformat |
deepgramSmartFormat |
| 174 |
ignorebackchannel |
ignoreBackchannel |
Every other attribute in the same class is correct camelCase (ttsLanguage, transcriptionProvider, speechModel, interruptSensitivity, …), and Gather.java:261 correctly emits speechTimeout for the same concept.
Reproduction
String xml = new VoiceResponse.Builder()
.connect(new Connect.Builder()
.conversationRelay(new ConversationRelay.Builder()
.url("wss://example.com/ws")
.speechtimeout("2000")
.build())
.build())
.build()
.toXml();
Produces <ConversationRelay url="wss://example.com/ws" speechtimeout="2000"/>; expected speechTimeout="2000".
Impact
Observed in production: a speechtimeout="2000" setting had no effect on end-of-speech reporting. Measured delay from end of caller speech to the prompt WebSocket frame across four utterances in one call was 0.45s / 0.61s / 0.95s / 1.17; all well under the configured 2000ms, consistent with the attribute being dropped and the default auto applying.
The failure is silent, which makes it costly: the config looks applied in code review and in the generated TwiML, and only careful timing analysis reveals it isn't.
Summary
ConversationRelayserializes four attributes in all-lowercase, but the ConversationRelay TwiML docs document them in camelCase. XML attributes are case-sensitive, so these are silently ignored by the TwiML parser — the setting appears to apply but has no effect, with no error surfaced.Affected attributes
src/main/java/com/twilio/twiml/voice/ConversationRelay.java:backgroundnoisereductionbackgroundNoiseReductionspeechtimeoutspeechTimeoutdeepgramsmartformatdeepgramSmartFormatignorebackchannelignoreBackchannelEvery other attribute in the same class is correct camelCase (
ttsLanguage,transcriptionProvider,speechModel,interruptSensitivity, …), andGather.java:261correctly emitsspeechTimeoutfor the same concept.Reproduction
Produces
<ConversationRelay url="wss://example.com/ws" speechtimeout="2000"/>; expectedspeechTimeout="2000".Impact
Observed in production: a
speechtimeout="2000"setting had no effect on end-of-speech reporting. Measured delay from end of caller speech to thepromptWebSocket frame across four utterances in one call was 0.45s / 0.61s / 0.95s / 1.17; all well under the configured 2000ms, consistent with the attribute being dropped and the defaultautoapplying.The failure is silent, which makes it costly: the config looks applied in code review and in the generated TwiML, and only careful timing analysis reveals it isn't.