chenhg5/cc-connect · error

: aes_key must be 16 raw bytes or 32-char hex…

Error message

%s: aes_key must be 16 raw bytes or 32-char hex (base64-wrapped), got %d bytes after base64

What it means

parseAesKey received a CDNMedia aes_key whose base64-decoded length is neither 16 raw bytes nor 32 bytes of hex ASCII — i.e. the key format is not one of the two layouts Weixin produces, so the media AES key cannot be derived for decrypting the CDN download.

Solutions

  1. Log the offending byte length and label to identify which message/media produced the malformed key
  2. Verify the aes_key was not truncated or re-encoded in transit (double base64, URL-escaped)
  3. Handle the failure by skipping the affected media and notifying rather than dropping the whole message
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at platform/weixin/cdn.go:109 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/9524fdde27b17d87. Report an issue: GitHub.

Appendix: source

Thrown at platform/weixin/cdn.go:109

func parseAesKey(aesKeyBase64, label string) ([]byte, error) {
	decoded, err := base64.StdEncoding.DecodeString(strings.TrimSpace(aesKeyBase64))
	if err != nil {
		return nil, fmt.Errorf("%s: aes_key base64: %w", label, err)
	}
	if len(decoded) == 16 {
		return decoded, nil
	}
	if len(decoded) == 32 {
		s := string(decoded)
		if hex32RE.MatchString(s) {
			k, err := hex.DecodeString(s)
			if err != nil {
				return nil, fmt.Errorf("%s: aes_key hex inside base64: %w", label, err)
			}
			return k, nil
		}
	}
	return nil, fmt.Errorf("%s: aes_key must be 16 raw bytes or 32-char hex (base64-wrapped), got %d bytes after base64", label, len(decoded))
}

func buildCdnDownloadURL(encryptedQueryParam, cdnBase string) string {
	return fmt.Sprintf("%s/download?encrypted_query_param=%s",
		strings.TrimRight(cdnBase, "/"),
		url.QueryEscape(encryptedQueryParam))
}

func buildCdnUploadURL(cdnBase, uploadParam, filekey string) string {
	return fmt.Sprintf("%s/upload?encrypted_query_param=%s&filekey=%s",
		strings.TrimRight(cdnBase, "/"),
		url.QueryEscape(uploadParam),
		url.QueryEscape(filekey))
}

func fetchCdnBytes(ctx context.Context, client *http.Client, fullURL, label string) ([]byte, error) {
	if client == nil {
		client = http.DefaultClient

View on GitHub (pinned to 4000b2338a)