{"record":{"id":"5819eec76cf9cb37","repo":"jumpserver/jumpserver","slug":"close-session-failed","errorCode":null,"errorMessage":"close session failed","messagePattern":"close session failed","errorType":"exception","errorClass":"GMDeviceError","httpStatus":null,"severity":"warning","filePath":"apps/common/sdk/gm/base/session.py","lineNumber":74,"sourceCode":"        signature = ECCSignature((c_ubyte * len(r))(*r), (c_ubyte * len(s))(*s))\n\n        plain_text = (c_ubyte * len(raw_data))(*raw_data)\n        ret = self._driver.SDF_ExternalVerify_ECC(\n            self._session,\n            c_int(alg_id),\n            pointer(pk),\n            plain_text,\n            c_int(len(plain_text)),\n            pointer(signature),\n        )\n        if ret != 0:\n            raise GMDeviceError(\"verify_sign\", ret)\n        return True\n\n    def close(self):\n        ret = self._driver.SDF_CloseSession(self._session)\n        if ret != 0:\n            raise GMDeviceError(\"close session failed\", ret)","sourceCodeStart":56,"sourceCodeEnd":74,"githubUrl":"https://github.com/jumpserver/jumpserver/blob/6ec464fabd61b95912d539455a3a5f15f5c59fe0/apps/common/sdk/gm/base/session.py#L56-L74","documentation":"SDF_CloseSession returned non-zero while closing the session, so the device refused or failed the session teardown. Resources on the device may or may not have been released; the error usually indicates a stale/invalid session handle.","triggerScenarios":"Calling session.close() twice, or after the device was reset/disconnected, or when the underlying handle was already invalidated.","commonSituations":"Double-close in cleanup/finally paths across exceptions; device daemon restarted while the session was open; long-lived process holding a session past device timeout.","solutions":["Make close() idempotent in your wrapper (track a closed flag) and only close once","If the device was reset, treat close failure as benign after logging the ret code","Wrap cleanup in try/except so a failed close doesn't mask the original error","Re-open device/session on next use rather than reusing a stale handle"],"exampleFix":"# before\nsession.close()  # in finally, may raise close session failed on second call\n\n# after\nclass SafeSession:\n    def __init__(self, s): self._s = s; self._closed = False\n    def close(self):\n        if self._closed: return\n        self._closed = True\n        try:\n            self._s.close()\n        except Exception as e:\n            logging.warning(\"session close failed: %s\", e)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    session.close()\nexcept GMDeviceError as e:\n    logging.warning(\"close session failed code=%s (likely already closed)\", e.args[1])","preventionTips":["Track closed state and close exactly once","Do cleanup in finally but swallow/log close errors","Re-open a fresh session rather than reusing handles after device resets"],"tags":["gm-crypto","sdf","session-cleanup"],"backgroundTag":"session-close-failed","analyzedSha":"6ec464fabd61b95912d539455a3a5f15f5c59fe0","analyzedAt":"2026-08-28T11:33:00.925Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}