arduino/Arduino · error · Exception
Unexpected %s response header: %s
Error message
Unexpected %s response header: %s
What it means
The NTLM connection pool wraps urllib3's connection creation in an NTLM handshake: on connect it sends the negotiate header and then scans the WWW-Authenticate response header for a token starting with 'NTLM ' to extract the server challenge. If the response header contains no such NTLM token, _new_conn raises this generic Exception because the server did not reply with the NTLM challenge the handshake requires.
Source
Thrown at arduino-core/src/processing/app/i18n/python/requests/packages/urllib3/contrib/ntlmpool.py:83
conn.request('GET', self.authurl, None, headers)
res = conn.getresponse()
reshdr = dict(res.getheaders())
log.debug('Response status: %s %s' % (res.status, res.reason))
log.debug('Response headers: %s' % reshdr)
log.debug('Response data: %s [...]' % res.read(100))
# Remove the reference to the socket, so that it can not be closed by
# the response object (we want to keep the socket open)
res.fp = None
# Server should respond with a challenge message
auth_header_values = reshdr[resp_header].split(', ')
auth_header_value = None
for s in auth_header_values:
if s[:5] == 'NTLM ':
auth_header_value = s[5:]
if auth_header_value is None:
raise Exception('Unexpected %s response header: %s' %
(resp_header, reshdr[resp_header]))
# Send authentication message
ServerChallenge, NegotiateFlags = \
ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value)
auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge,
self.user,
self.domain,
self.pw,
NegotiateFlags)
headers[req_header] = 'NTLM %s' % auth_msg
log.debug('Request headers: %s' % headers)
conn.request('GET', self.authurl, None, headers)
res = conn.getresponse()
log.debug('Response status: %s %s' % (res.status, res.reason))
log.debug('Response headers: %s' % dict(res.getheaders()))
log.debug('Response data: %s [...]' % res.read()[:100])
if res.status != 200:View on GitHub (pinned to a0df6e0e83)
Solutions
- Inspect the raw WWW-Authenticate header returned by the server (curl -v or res.getheaders()) and confirm whether NTLM is offered.
- If the server only offers Negotiate/Kerberos, use a Kerberos-capable client (e.g. requests-kerberos) instead of NTLMConnectionPool, or enable NTLM on the server/proxy.
- Check for intermediaries (proxies, load balancers) stripping or rewriting WWW-Authenticate and whitelist the NTLM header.
- If only Basic auth is available, use a normal urllib3/requests pool with HTTPBasicAuth instead of the NTLM pool.
Example fix
// before
pool = NTLMConnectionPool(host='proxy.corp', username=user, password=pwd) # server only does Negotiate
// after
import requests
resp = requests.get('http://proxy.corp/path', auth=(user, pwd)) # or configure NTLM on the proxy Defensive patterns
Strategy: validation
Validate before calling
def server_offers_ntlm(host, port=80, path='/'):
import http.client
conn = http.client.HTTPConnection(host, port)
conn.request('GET', path)
hdr = conn.getresponse().getheader('WWW-Authenticate', '')
return 'NTLM' in hdr Type guard
def is_ntlm_challenge(www_authenticate_value):
return isinstance(www_authenticate_value, str) and 'NTLM ' in www_authenticate_value Try / catch
try:
conn = ntlm_pool._new_conn()
except Exception as e:
if 'Unexpected' in str(e) and 'response header' in str(e):
log.error('Server did not answer with an NTLM challenge: %s', e)
# fall back to basic auth or a plain pool
else:
raise Prevention
- Probe WWW-Authenticate on the target before wiring up NTLMConnectionPool.
- Confirm proxy/load balancers preserve the WWW-Authenticate header.
- Enable NTLM (or use Negotiate with a Kerberos client) on servers that only offer Kerberos.
- Keep ntlm/ python-ntlm dependencies installed — a missing parse module can also break the exchange.
When it happens
Trigger: Creating an NTLMConnectionPool and issuing a request when the server's WWW-Authenticate response does not include a 'NTLM <base64>' token — e.g. the server only offers Negotiate/Basic auth, sends a malformed header, or the pool is pointed at a non-NTLM endpoint.
Common situations: Pointing NTLMConnectionPool at a proxy or IIS server configured for Kerberos/Negotiate only; header mangled by a proxy that strips WWW-Authenticate; connecting to a plain HTTP service that does not speak NTLM at all.
Related errors
- Server rejected request: wrong username or password
- Wrong server response: %s %s
- Unable to understand proxy settings
- Unable to fetch PAC file at {pac}. Response code is {respons
- SSLError(e)
AI-assisted analysis of arduino/Arduino@a0df6e0e83 (2026-09-06).
Data as JSON: /api/errors/574fed9f2e943c1f.
Report an issue: GitHub.