dromara/Sa-Token · error · SaOAuth2ClientModelException

30105

30105

Error message

无效 client_id: 

What it means

Thrown by SaOAuth2Template.checkClientModel: no SaClientModel exists for the given client_id (the data loader returned null). This is the primary 'unknown client' error for every OAuth2 endpoint that validates a client. It is thrown as SaOAuth2ClientModelException carrying the clientId. Error code 30105.

Source

Thrown at sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/template/SaOAuth2Template.java:61

	/**
	 * 获取 ClientModel,根据 clientId
	 *
	 * @param clientId /
	 * @return /
	 */
	public SaClientModel getClientModel(String clientId) {
		return SaOAuth2Manager.getDataLoader().getClientModel(clientId);
	}

	/**
	 * 校验 clientId 信息并返回 ClientModel,如果找不到对应 Client 信息则抛出异常
	 * @param clientId /
	 * @return /
	 */
	public SaClientModel checkClientModel(String clientId) {
		SaClientModel clientModel = getClientModel(clientId);
		if(clientModel == null) {
			throw new SaOAuth2ClientModelException("无效 client_id: " + clientId)
					.setClientId(clientId)
					.setCode(SaOAuth2ErrorCode.CODE_30105);
		}
		return clientModel;
	}

	/**
	 * 校验:clientId 与 clientSecret 是否正确,正确返回 SaClientModel,不正确抛出异常
	 * @param clientId 应用id
	 * @param clientSecret 秘钥
	 * @return SaClientModel对象
	 */
	public SaClientModel checkClientSecret(String clientId, String clientSecret) {
		SaClientModel cm = checkClientModel(clientId);
		if(cm.clientSecret == null || ! cm.clientSecret.equals(clientSecret)) {
			throw new SaOAuth2ClientModelException("无效 client_secret: " + clientSecret)
					.setClientId(clientId)
					.setCode(SaOAuth2ErrorCode.CODE_30115);

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Verify the client_id exists in the active registration source (SaOAuth2DataLoader / configured client list / redis)
  2. Confirm environment alignment: the service the client calls is the one where the client is registered
  3. Implement/verify SaOAuth2DataLoader.getClientModel returns a SaClientModel for that exact id

Example fix

// before
@Override
public SaClientModel getClientModel(String clientId) {
    return null; // never registered
}

// after
@Override
public SaClientModel getClientModel(String clientId) {
    return clients.get(clientId); // pre-loaded map: "1001" -> SaClientModel
}
Defensive patterns

Strategy: try-catch

Validate before calling

if(SaOAuth2Manager.getDataLoader().getClientModel(clientId) == null) {
    throw new IllegalArgumentException("unknown client_id: " + clientId);
}

Try / catch

catch(SaOAuth2ClientModelException e) {
    if("30105".equals(e.getCode())) return 400 "unknown client_id"; // e.getClientId() available
}

Prevention

When it happens

Trigger: Any authorize/token request with an unregistered client_id; client_id correct in one environment but the service points at another data loader/redis DB; client registration written to a store the oauth2-server does not read.

Common situations: Test vs production client registries differ; SaClientModel list configured in application.yml but a custom data loader overrides it and returns null; typo in client_id; registration lost after cache/redis flush.

Related errors


AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14). Data as JSON: /api/errors/8a503375dd134720. Report an issue: GitHub.