JeffreySu/WeiXinMPSDK · error · WxOpenException

SessionId无效

Error message

SessionId无效

What it means

Thrown by DecodeEncryptedDataBySessionId when SessionContainer.GetSession(sessionId) finds no session, so the encrypted data cannot be decrypted with a SessionKey. Raises WxOpenException "SessionId无效". Same family as CheckSignature's (01) error but in the decryption path.

Solutions

  1. Decrypt encrypted data soon after login while the session is still cached, or re-login to refresh the session
  2. Configure a shared distributed cache for SessionContainer across all instances
  3. Check session existence first with SessionContainer.GetSession(sessionId) and trigger re-login when null
  4. Catch WxOpenException and return a session-expired error code to the mini-program

Example fix

// before
var json = EncryptHelper.DecodeEncryptedDataBySessionId(sessionId, encryptedData, iv); // throws
// after
if (SessionContainer.GetSession(sessionId) == null) {
    return LoginExpired(); // client re-runs wx.login
}
var json = EncryptHelper.DecodeEncryptedDataBySessionId(sessionId, encryptedData, iv);
Defensive patterns

Strategy: validation

Validate before calling

if (SessionContainer.GetSession(sessionId) == null) {
    return RequireRelogin(); // re-run wx.login + jscode2session
}

Type guard

bool CanDecrypt(string sessionId) => SessionContainer.GetSession(sessionId) != null;

Try / catch

try {
    var json = EncryptHelper.DecodeEncryptedDataBySessionId(sessionId, encryptedData, iv);
} catch (WxOpenException ex) when (ex.Message.Contains("SessionId无效")) {
    return Unauthorized("session expired");
}

Prevention

When it happens

Trigger: Calling DecodeEncryptedDataBySessionId(sessionId, encryptedData, iv) with an expired/unknown sessionId; using a sessionId obtained before a cache restart or on a different server without shared cache; client sending a wrong or fabricated id.

Common situations: Memory-cache eviction/timeout between login and decrypt (e.g. phone-number decrypt long after login); load-balanced servers each with local cache; stale frontend session after server redeploy.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12). Data as JSON: /api/errors/c0f406a845fd2a0c. Report an issue: GitHub.

Appendix: source

Thrown at src/Senparc.Weixin.WxOpen/src/Senparc.Weixin.WxOpen/Senparc.Weixin.WxOpen/Helpers/EncryptHelper.cs:251

            var result = AES_Decrypt(encryptedData, aesIV, aesKey, keySize);
            var resultStr = Encoding.UTF8.GetString(result);
            return resultStr;
        }

        /// <summary>
        /// 解密消息(通过SessionId获取)
        /// </summary>
        /// <param name="sessionId"></param>
        /// <param name="encryptedData"></param>
        /// <param name="iv"></param>
        /// <exception cref="WxOpenException">当SessionId或SessionKey无效时抛出异常</exception>
        /// <returns></returns>
        public static string DecodeEncryptedDataBySessionId(string sessionId, string encryptedData, string iv)
        {
            var sessionBag = SessionContainer.GetSession(sessionId);
            if (sessionBag == null)
            {
                throw new WxOpenException("SessionId无效");
            }

            if (string.IsNullOrEmpty(sessionBag.SessionKey))
            {
                throw new WxOpenException("SessionKey无效");
            }

            var resultStr = DecodeEncryptedData(sessionBag.SessionKey, encryptedData, iv);
            return resultStr;
        }


        /// <summary>
        /// 检查解密消息水印
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="appId"></param>
        /// <returns>entity为null时也会返回false</returns>

View on GitHub (pinned to be573f6f94)