dromara/Sa-Token · error · IllegalArgumentException

无效字符:

Error message

无效字符: 

What it means

Thrown by SaSerializerForBase64UseCustomCharacters.stringToBytes when a character in the encoded string (other than the pad char) is not present in the configured 64-character custom alphabet (IllegalArgumentException '无效字符: c'). The decoder maps each character to its index in CUSTOM_CHARS; an unknown character means the string was not produced by this alphabet.

Source

Thrown at sa-token-plugin/sa-token-serializer-features/src/main/java/cn/dev33/satoken/serializer/SaSerializerForBase64UseCustomCharacters.java:124

		int paddingCount = 0;
		for (int i = length - 1; i >= 0 && encodedStr.charAt(i) == PAD_CHAR; i--) {
			paddingCount++;
		}

		int numGroups = length / 4;
		byte[] decoded = new byte[numGroups * 3 - paddingCount];
		int decodedIndex = 0;

		for (int group = 0; group < numGroups; group++) {
			int[] indices = new int[4];
			for (int j = 0; j < 4; j++) {
				char c = encodedStr.charAt(group * 4 + j);
				if (c == PAD_CHAR) {
					indices[j] = 0; // 填充符处理为0,后续根据paddingCount调整
				} else {
					Integer index = charMap.get(c);
					if (index == null) {
						throw new IllegalArgumentException("无效字符: " + c);
					}
					indices[j] = index;
				}
			}

			int combined = (indices[0] << 18) | (indices[1] << 12) | (indices[2] << 6) | indices[3];
			for (int k = 0; k < 3; k++) {
				if (decodedIndex < decoded.length) {
					decoded[decodedIndex++] = (byte) ((combined >> (16 - 8 * k)) & 0xFF);
				}
			}
		}

		return decoded;
	}
}

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Make the writer and reader use the exact same CUSTOM_CHARS string (same order), ideally defined in one shared constant
  2. If the data is standard Base64, use the standard serializer instead of the custom-characters one
  3. Treat CUSTOM_CHARS as immutable after first release; changing it invalidates all previously serialized values
Defensive patterns

Strategy: validation

Validate before calling

java.util.Set<Character> alphabet = new java.util.HashSet<>();
for (char c : CUSTOM_CHARS.toCharArray()) alphabet.add(c);
boolean ok = input.chars().allMatch(c -> alphabet.contains((char) c) || c == PAD_CHAR);
if (!ok) throw new IllegalArgumentException("string contains chars outside the custom alphabet");

Try / catch

try { byte[] data = serializer.stringToBytes(input); } catch (IllegalArgumentException e) { log.warn("alphabet mismatch on decode"); reSerializeFromSource(); }

Prevention

When it happens

Trigger: Deserializing a standard Base64 string (containing '+', '/', '=') while the custom alphabet excludes those characters, or mixing two different custom alphabets between the writer and reader.

Common situations: Swapping CUSTOM_CHARS order between versions/services so previously valid encodings now decode differently or fail; standard Base64 tokens fed to the custom serializer; copy-paste introduces a look-alike Unicode character.

Related errors


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