{"record":{"id":"3d8b4ce18c9e937b","repo":"XX-net/XX-Net","slug":"fetch-gae-fail-d","errorCode":null,"errorMessage":"fetch gae fail:%d","messagePattern":"fetch gae fail:(.+?)","errorType":"exception","errorClass":"GAE_Exception","httpStatus":null,"severity":"error","filePath":"code/default/gae_proxy/local/gae_handler.py","lineNumber":330,"sourceCode":"\n        return response\n    except Exception as e:\n        response.worker.close(\"unpack protocol error\")\n        raise GAE_Exception(600, \"unpack protocol:%r at:%s\" % (e, traceback.format_exc()))\n\n\ndef request_gae_server(headers, body, url, timeout):\n    # process on http protocol\n    # process status code return by http server\n    # raise error, let up layer retry.\n\n    try:\n        response = front.request(b\"POST\", b\"\", b\"/_gh/\", headers, body, timeout)\n        if not response:\n            raise GAE_Exception(600, \"fetch gae fail\")\n\n        if response.status >= 600:\n            raise GAE_Exception(\n                response.status, \"fetch gae fail:%d\" % response.status)\n\n        appid = response.ssl_sock.host.split(\".\")[0]\n        if response.status == 404:\n            # xlog.warning('APPID %r not exists, remove it.', response.ssl_sock.appid)\n            front.appid_manager.report_not_exist(\n                appid, response.ssl_sock.ip_str)\n            # google_ip.report_connect_closed(response.ssl_sock.ip_str, \"appid not exist\")\n            response.worker.close(\"appid not exist:%s\" % appid)\n            raise GAE_Exception(603, \"appid not exist %s\" % appid)\n\n        if response.status == 503:\n            xlog.warning('APPID %r out of Quota, remove it. %s',\n                         appid, response.ssl_sock.ip_str)\n            front.appid_manager.report_out_of_quota(appid)\n            # google_ip.report_connect_closed(response.ssl_sock.ip_str, \"out of quota\")\n            response.worker.close(\"appid out of quota:%s\" % appid)\n            raise GAE_Exception(604, \"appid out of quota:%s\" % appid)","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/XX-net/XX-Net/blob/cfa5bc17b67676e467f37ec50766127e0ab5f0aa/code/default/gae_proxy/local/gae_handler.py#L312-L348","documentation":"GAE_Exception thrown when the frontend returns a synthetic status >= 600 (XX-Net uses 600+ internally to signal transport errors through the status field). The message includes the pseudo-status number, e.g. 600 for connection issues, distinguishing it from real HTTP statuses.","triggerScenarios":"request_gae_proxy calls where front.request encounters a connection-level error and encodes it as an internal status >= 600 instead of raising directly; e.g. TLS handshake failure or reset during the POST /_gh/ request.","commonSituations":"Connection reset mid-request by firewall, Google IP flakiness, SNI-based blocking of the selected IP.","solutions":["Retry — the handler retries on GAE_Exception and will pick another connection/IP","Update XX-Net; IP blocking patterns change and newer versions adapt","Check whether other Google IPs work (XX-Net status page) and let the scanner refresh the IP pool"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    resp = request_gae_proxy(...)\nexcept GAE_Exception as e:\n    if e.code >= 600:  # synthetic transport status\n        resp = request_gae_proxy(...)  # picks new connection\n    else:\n        raise","preventionTips":["Treat any status >= 600 as internal/transport, never as a real HTTP status","Let the connection pool recycle failing workers (request already closes them)","Keep the app updated to benefit from improved connection handling"],"tags":["gae-proxy","network","internal-status"],"backgroundTag":"backend-unreachable","analyzedSha":"cfa5bc17b67676e467f37ec50766127e0ab5f0aa","analyzedAt":"2026-08-27T19:28:28.225Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}