dromara/Sa-Token · error · SaOAuth2AuthorizationCodeException

30110

30110

Error message

无效 code: 

What it means

Thrown by SaOAuth2Template.checkCode when the authorization code cannot be found in the DAO (code 30110, SaOAuth2AuthorizationCodeException). Codes are short-lived, single-use server-issued credentials; a miss means the code was never issued, already consumed, expired, or lost (e.g. different DAO/Redis node).

Source

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

	/**
	 * 获取 CodeModel,无效的 code 会返回 null
	 * @param code /
	 * @return /
	 */
	public CodeModel getCode(String code) {
		return SaOAuth2Manager.getDao().getCode(code);
	}

	/**
	 * 校验 Code,成功返回 CodeModel,失败则抛出异常
	 * @param code /
	 * @return /
	 */
	public CodeModel checkCode(String code) {
		CodeModel cm = SaOAuth2Manager.getDao().getCode(code);
		if(cm == null) {
			throw new SaOAuth2AuthorizationCodeException("无效 code: " + code)
					.setAuthorizationCode(code)
					.setCode(SaOAuth2ErrorCode.CODE_30110);
		}
		return cm;
	}

	/**
	 * 获取 Code,根据索引: clientId、loginId
	 * @param clientId /
	 * @param loginId /
	 * @return /
	 */
	public String getCodeValue(String clientId, Object loginId) {
		return SaOAuth2Manager.getDao().getCodeValue(clientId, loginId);
	}


	// ----------------- Access-Token 相关 -----------------

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Confirm the code is sent exactly as issued and URL-encoded in the token request
  2. Redo the authorize flow to get a fresh code — codes are single-use and expire quickly (default ~5 min)
  3. If running multiple OAuth2 server nodes, ensure they share the same Redis DAO so codes are visible cluster-wide
Defensive patterns

Strategy: retry

Validate before calling

if (SaFoxUtil.isEmpty(code)) throw new IllegalArgumentException("code is empty");
if (SaOAuth2Manager.getDao().getCode(code) == null) { /* code dead -> restart flow */ }

Try / catch

try { return saOAuth2Template.checkCode(code); } catch (SaOAuth2AuthorizationCodeException e) { redirectUserToAuthorize(); // get fresh code
 return null; }

Prevention

When it happens

Trigger: Calling the token endpoint (/oauth2/token?grant_type=authorization_code) with a code that was already redeemed, has expired past its configured timeout, was truncated/URL-mangled, or when the server DAO was flushed/restarted with memory storage.

Common situations: Double submission of the token request (browser retry, duplicate HTTP call); front-end losing characters of the code due to missing URL encoding; dev server restart clearing in-memory code cache; multiple instances without shared Redis.

Related errors


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