Twilio error 12300 means your webhook server returned an HTTP response with a Content-Type header that Twilio does not accept as a valid TwiML content type. Twilio requires TwiML responses to have a Content-Type of either text/xml or application/xml, and it rejects responses with any other Content-Type (including text/html, application/json, text/plain, or no Content-Type at all) with this error. This is a strict header validation check that happens before Twilio attempts to parse the response body.
What Causes This Error
The most common cause is a web framework that sets a default Content-Type of application/json or text/html for all responses unless explicitly overridden, and a developer who writes the TwiML XML body correctly but does not set the Content-Type header explicitly, resulting in the framework's default being sent instead. Error handling middleware that returns HTML error pages (the classic white page with a stack trace, or a styled 500 error page) when your webhook throws an unhandled exception is a second cause: the exception page is returned with Content-Type text/html, which Twilio rejects with 12300. A CDN or reverse proxy configured to cache and serve static assets can sometimes intercept requests to webhook paths and serve a cached response with an incorrect Content-Type header if the cache was seeded with a non-XML response. Returning a JSON response from your webhook handler because the developer intended to return diagnostic information or a success confirmation rather than TwiML is a development-time mistake that also produces 12300.
How to Fix It Step by Step
Set the Content-Type response header explicitly in your webhook handler to text/xml before writing any response body: in Express (Node.js) use res.set('Content-Type', 'text/xml'), in Flask (Python) use return Response(twiml_string, mimetype='text/xml'), in Rails use render xml: twiml_string, content_type: 'text/xml', and in PHP use header('Content-Type: text/xml'). Use curl -I https://your-webhook-url to retrieve only the response headers from your webhook and confirm the Content-Type header is present and set to text/xml, before it reaches Twilio. Check your error handling and exception logging middleware to ensure that when your webhook throws an exception, the error response still sets Content-Type to text/xml and returns a safe fallback TwiML document (such as a minimal Response with a Say verb and a Hangup) rather than an HTML stack trace page. If you use the official Twilio helper library, return the TwiML response using the library's built-in response method rather than converting the TwiML builder output to a raw string and returning it yourself, since the library's response methods set the correct Content-Type header automatically in most framework integrations.
How to Prevent It from Recurring
Create a reusable TwiML response helper function in your codebase that always sets Content-Type to text/xml and returns a properly structured response, and require all webhook handlers to use this helper function rather than constructing responses directly, centralizing the Content-Type setting in one place. Add an integration test that makes an actual HTTP request to each webhook endpoint and asserts that the response Content-Type header is exactly text/xml, running this test on every CI build to catch Content-Type regressions before deployment. Configure your error handling middleware to set a Content-Type of text/xml and return a minimal fallback TwiML document for any unhandled exception, so that even when your webhook handler crashes, Twilio receives a valid TwiML response rather than an HTML error page with an incorrect Content-Type. Audit your CDN and reverse proxy configuration for any rules that transform or override Content-Type headers on responses from your webhook endpoints, and add explicit rules that preserve the text/xml Content-Type through the entire response pipeline.
When to Call a Specialist
If you have set the Content-Type header correctly in your application code and verified it with curl but Twilio still reports 12300, a middleware or infrastructure component in your stack is overwriting the header after your application sets it, which requires tracing the response through every layer of your stack to identify where the override occurs. A specialist can configure a packet capture or proxy between your CDN and Twilio to observe the exact headers in the response Twilio receives, identifying precisely which infrastructure layer is modifying the Content-Type. You should also seek specialist help if 12300 errors are intermittent and only occur on a small percentage of requests, as this pattern suggests a race condition or a fallback code path in your error handling that occasionally returns the wrong Content-Type rather than a systematic misconfiguration. Intermittent Content-Type errors during production voice calls cause dropped calls and frustrated customers, and fast specialist diagnosis is worth the investment.
Conclusion
Error 12300 is a Content-Type header mismatch that is fixed in two lines of code by setting text/xml explicitly on every TwiML response and ensuring error handlers do the same. If this error is blocking your production system, contact our team and we will diagnose and fix it within the hour.
Ready to Transform Your Business Communications?
Get a free consultation with our VoIP experts and discover how we can help you save costs, improve efficiency, and scale your business.
Comments (0)
Join the discussion and share your thoughts (AI-moderated for quality)
Be the first to comment
No comments yet. Share your thoughts below.