arduino/Arduino · error · Exception

Wrong server response: %s %s

Error message

Wrong server response: %s %s

What it means

In the same final-leg check of ntlmpool._new_conn, any non-200 status that is not 401 raises 'Wrong server response: <status> <reason>'. The NTLM handshake succeeded at the transport level but the server returned something the pool cannot interpret as an authenticated connection, so it aborts with this generic Exception.

Source

Thrown at arduino-core/src/processing/app/i18n/python/requests/packages/urllib3/contrib/ntlmpool.py:105

        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:
            if res.status == 401:
                raise Exception('Server rejected request: wrong '
                                'username or password')
            raise Exception('Wrong server response: %s %s' %
                            (res.status, res.reason))

        res.fp = None
        log.debug('Connection established')
        return conn

    def urlopen(self, method, url, body=None, headers=None, retries=3,
                redirect=True, assert_same_host=True):
        if headers is None:
            headers = {}
        headers['Connection'] = 'Keep-Alive'
        return super(NTLMConnectionPool, self).urlopen(method, url, body,
                                                       headers, retries,
                                                       redirect,
                                                       assert_same_host)

View on GitHub (pinned to a0df6e0e83)

Solutions

  1. Read the logged status/reason (log.debug prints it) and address the underlying HTTP status: 403 → fix permissions, 404 → fix the host/path configured on the pool.
  2. Retry the request — NTLM connection setup can race with server-side state; a fresh request sometimes completes cleanly.
  3. Bypass intermediaries (proxy/load balancer) or check their logs if the status is 5xx and direct connection works.
  4. If the server intermittently drops NTLM support, fall back to a plain pool or a different auth scheme the server reliably offers.

Example fix

// before (403 from wrong path)
pool.request('GET', '/admin/config')  # user has no rights
// after
pool.request('GET', '/public/status')  # resource the authenticated user may access
Defensive patterns

Strategy: retry

Validate before calling

def check_resource_available(base_url, path):
    import requests
    r = requests.head(base_url + path, allow_redirects=False)
    return r.status_code < 400, r.status_code

Type guard

def is_auth_handshake_success(status):
    return status == 200

Try / catch

import time
for attempt in range(3):
    try:
        resp = ntlm_pool.urlopen('GET', path)
        break
    except Exception as e:
        if 'Wrong server response' in str(e) and attempt < 2:
            time.sleep(2 ** attempt)
            continue
        raise

Prevention

When it happens

Trigger: Completing the NTLM authenticate exchange but receiving e.g. 403 (insufficient permissions on the target resource), 404/500 (bad target path or server error), or 502/503 from an intermediary during an NTLMConnectionPool request.

Common situations: Authenticated user lacks rights to the requested resource (403); the configured host/path on the pool is wrong (404); upstream application error (500); corporate proxy returning 502/503 mid-handshake.

Related errors


AI-assisted analysis of arduino/Arduino@a0df6e0e83 (2026-09-06). Data as JSON: /api/errors/40a18d9da8648610. Report an issue: GitHub.