iflytek/astron-agent · critical · BusinessException

WECHAT_VERIFY_TICKET_MISSING

WECHAT_VERIFY_TICKET_MISSING

Error message

WECHAT_VERIFY_TICKET_MISSING

What it means

WECHAT_VERIFY_TICKET_MISSING is thrown by getComponentAccessToken when the Redis bucket COMPONENT_VERIFY_TICKET_KEY holds no value. WeChat pushes the component_verify_ticket every 10 minutes; without a stored ticket the component_access_token cannot be requested.

Solutions

  1. Verify the ticket-receiving endpoint is configured as the authorized-event URL in WeChat Open Platform and returns success to WeChat's pushes
  2. Check Redis for COMPONENT_VERIFY_TICKET_KEY; if absent, wait for the next 10-minute push or trigger WeChat to resend by restarting ticket receipt
  3. Confirm the component appid/encoding/AES key so ticket push messages decrypt and store correctly
  4. Check logs of the ticket handler for decryption or storage failures

Example fix

// before
String componentVerifyTicket = ticketBucket.get();
if (!StringUtils.hasText(componentVerifyTicket)) {
    throw new BusinessException(ResponseEnum.WECHAT_VERIFY_TICKET_MISSING);
}
// after
String componentVerifyTicket = ticketBucket.get();
if (!StringUtils.hasText(componentVerifyTicket)) {
    log.error("component_verify_ticket missing in Redis; check ticket push endpoint and redis persistence");
    throw new BusinessException(ResponseEnum.WECHAT_VERIFY_TICKET_MISSING);
}
// root fix: ensure the ticket callback stores it:
redissonClient.getBucket(COMPONENT_VERIFY_TICKET_KEY).set(ticket, 11, TimeUnit.MINUTES);
Defensive patterns

Strategy: fallback

Validate before calling

// pre-check before requesting a component token
String ticket = redissonClient.getBucket(COMPONENT_VERIFY_TICKET_KEY).get();
if (!StringUtils.hasText(ticket)) {
    // fail fast / alert ops: WeChat ticket push is not being received
}

Try / catch

try {
    String token = wechatThirdpartyService.componentAccessToken();
} catch (BusinessException e) {
    if (ResponseEnum.WECHAT_VERIFY_TICKET_MISSING.getCode().equals(e.getCode())) {
        alertOps("component_verify_ticket missing — check ticket push endpoint and Redis");
        // back off and retry after the next 10-minute WeChat push
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling getComponentAccessToken before WeChat ever delivered a verify ticket (fresh deployment, ticket push endpoint not configured/receiving), after Redis was flushed/persisted ticket expired, or the callback URL for ticket pushes is misconfigured in the WeChat open platform.

Common situations: New environment where the authorization ticket push URL isn't registered; Redis restart/eviction wiping the key; the message-handling endpoint that stores the ticket is down or rejecting WeChat's pushes; firewall blocking WeChat's callback servers.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/4628fb3cc417d250. Report an issue: GitHub.

Appendix: source

Thrown at console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/wechat/impl/WechatThirdpartyServiceImpl.java:203

        } catch (Exception e) {
            log.error("Failed to parse verify ticket from decrypted XML: {}", decryptedXml, e);
        }
    }

    @Override
    public String getComponentAccessToken() {
        RBucket<String> bucket = redissonClient.getBucket(COMPONENT_ACCESS_TOKEN_KEY);

        if (bucket.isExists()) {
            return bucket.get();
        }

        // Get verification ticket
        RBucket<String> ticketBucket = redissonClient.getBucket(COMPONENT_VERIFY_TICKET_KEY);
        String componentVerifyTicket = ticketBucket.get();

        if (!StringUtils.hasText(componentVerifyTicket)) {
            throw new BusinessException(ResponseEnum.WECHAT_VERIFY_TICKET_MISSING);
        }

        // Call WeChat API to get access token
        String accessToken = requestComponentAccessTokenFromWechat(componentVerifyTicket);

        // Cache access token
        bucket.set(accessToken, ACCESS_TOKEN_EXPIRE);

        log.info("Third-party platform access token retrieved successfully");
        return accessToken;
    }

    /**
     * Set pre-binding status
     */
    private void setPreBindStatus(String appid, Integer botId, String uid) {
        String preBindKey = PRE_BIND_KEY + appid;
        RBucket<String> bucket = redissonClient.getBucket(preBindKey);

View on GitHub (pinned to 5e758547a8)