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
- Verify the ticket-receiving endpoint is configured as the authorized-event URL in WeChat Open Platform and returns success to WeChat's pushes
- 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
- Confirm the component appid/encoding/AES key so ticket push messages decrypt and store correctly
- 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
- Register the authorized-event URL in WeChat Open Platform and confirm it returns success
- Store the ticket in Redis with a TTL slightly longer than the 10-minute push interval
- Monitor the ticket key with an alert when it approaches expiry
- Verify AES/message decryption of ticket push messages after any appid/key change
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
- INTERNAL_SERVER_ERROR
- LONG_CONTENT_FILE_NUM_OUT_LIMIT
- size limit is invalid
- BOT_NOT_EXISTS
- PARAMS_ERROR
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)