w7corp/easywechat · error · HttpException

Failed to get jssdk agentTicket: %s

Error message

Failed to get jssdk agentTicket: %s

What it means

Thrown by JsApiTicket::getAgentTicket() when GET /cgi-bin/ticket/get?type=agent_config returns no ticket. This ticket is specific to agent-level JS-SDK config (wx.agentConfig), and like the corp ticket, a missing ticket field normally reflects an invalid underlying access_token or a permission problem for that agent.

Source

Thrown at src/Work/JsApiTicket.php:135

    }

    /**
     * @throws HttpException
     */
    public function getAgentTicket(int $agentId): string
    {
        $key = $this->getAgentKey($agentId);
        $ticket = $this->cache->get($key);

        if ($ticket && is_string($ticket)) {
            return $ticket;
        }

        $response = $this->httpClient->request('GET', '/cgi-bin/ticket/get', ['query' => ['type' => 'agent_config']])
            ->toArray(false);

        if (empty($response['ticket'])) {
            throw new HttpException('Failed to get jssdk agentTicket: '.json_encode($response, JSON_UNESCAPED_UNICODE));
        }

        $this->cache->set($key, $response['ticket'], intval($response['expires_in']));

        return $response['ticket'];
    }

    public function getAgentKey(int $agentId): string
    {
        return sprintf('%s.%s', $this->getKey(), $agentId);
    }
}

View on GitHub (pinned to f0cf0a8b83)

Solutions

  1. Read the errcode from the embedded JSON body in the exception message
  2. Verify the corpsecret used for access_token belongs to agentId passed to getAgentTicket()
  3. Flush cached access_token and the per-agent ticket key (getKey() . '.' . $agentId) and retry
  4. Confirm the agent has JS-SDK permission and the page domain is set as trusted domain for that agent

Example fix

// before
$ticket = $work->jsapi_ticket->getAgentTicket(1000002); // secret from agent 1000001
// after - fetch token with the same agent's secret
$config = ['corp_id' => 'ww1234', 'secret' => $secretOfAgent1000002];
$work = new \EasyWeChat\Work\Application($config);
$ticket = $work->jsapi_ticket->getAgentTicket(1000002);
Defensive patterns

Strategy: try-catch

Validate before calling

$agentSecrets = loadAgentSecrets();
if (! isset($agentSecrets[$agentId])) { throw new \InvalidArgumentException("no secret for agent {$agentId}"); }

Try / catch

use EasyWeChat\Kernel\Exceptions\HttpException;
try {
    $ticket = $work->jsapi_ticket->getAgentTicket($agentId);
} catch (HttpException $e) {
    // clear per-agent ticket + access token, ensure the token was built with THIS agent's secret
    $work->jsapi_ticket->cache->delete($work->jsapi_ticket->getAgentKey($agentId));
    $ticket = $work->jsapi_ticket->getAgentTicket($agentId);
}

Prevention

When it happens

Trigger: Calling getAgentTicket($agentId) (or wx.agentConfig signature building) on cache miss. Produced by invalid/expired access_token, wrong agent secret for the agentId used, the agent lacking API permission, or the page domain not being the agent's trusted domain (errcode 40029/61005 in embedded body).

Common situations: Rendering wx.agentConfig in an in-app chat page while the corp token was fetched with a different agent's secret; caching per-agent tickets under keys that collide after agentId changes; stale cached access_token after credential rotation.

Related errors


AI-assisted analysis of w7corp/easywechat@f0cf0a8b83 (2026-08-21). Data as JSON: /api/errors/3fa9955610bf77d0. Report an issue: GitHub.