iflytek/astron-agent · error
must contain 32-50 valid UTF-8 characters
Error message
%s must contain 32-50 valid UTF-8 characters
What it means
validateCredential enforces that each bootstrap credential (TENANT_KEY/TENANT_SECRET) is valid UTF-8 and between 32 and 50 characters (rune count). 'must contain 32-50 valid UTF-8 characters' fires when the value is invalid UTF-8, shorter than 32, or longer than 50 runes.
Solutions
- Regenerate or re-copy the credential ensuring it is 32-50 characters of ASCII letters/digits/._~- .
- Check for truncation: echo ${#TENANT_KEY} (or wc -m on the _FILE) and compare with the source secret.
- Ensure the secret file is plain UTF-8 without BOM or binary content; re-create it with printf rather than editors that add bytes.
- If using base64 secrets, decode before storing — the validator expects the raw value, not base64.
Example fix
// before TENANT_KEY=abc123 # 6 chars, too short // after TENANT_KEY=7b709739e8da44536127a333c7603a83 # 32 chars (use a fresh non-legacy value)
Defensive patterns
Strategy: validation
Validate before calling
func credentialLooksValid(v string) bool {
n := utf8.RuneCountInString(v)
return utf8.ValidString(v) && n >= 32 && n <= 50
} Prevention
- Check credential length (${#VAR}) when generating or rotating secrets.
- Generate keys as exactly 32 hex characters to stay within bounds.
- Never base64-encode unless you decode before injecting; the validator wants the raw value.
When it happens
Trigger: Validate or credentialFromEnvironmentOrFile calls validateCredential and the supplied value fails the length/UTF-8 check — e.g. a truncated env var, a base64 value pasted with extra characters, or binary/garbled bytes read from a file.
Common situations: Secret truncated by shell quoting or YAML parsing; value stored with a trailing newline counted before trim in a custom pipeline; ops pasted a hex key shorter than 32 chars; file encoding issue producing invalid UTF-8.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- TENANT_ID must remain
- must not contain control characters
- must contain only ASCII letters, digits, '.', '_', '~', or
- Remote resource URL must not include user information
- TENANT_KEY and TENANT_SECRET must be distinct values
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/a3b4a8c59e79cbd8.
Report an issue: GitHub.
Appendix: source
Thrown at core/tenant/config/bootstrap_credentials.go:139
}
if openedInfo.Size() > maxCredentialFileBytes {
return "", errors.New("credential file is too large")
}
data, err := io.ReadAll(io.LimitReader(file, maxCredentialFileBytes+1))
if err != nil {
return "", errors.New("credential file cannot be read")
}
if len(data) > maxCredentialFileBytes {
return "", errors.New("credential file is too large")
}
return strings.TrimSpace(string(data)), nil
}
func validateCredential(name, value string) error {
length := utf8.RuneCountInString(value)
if !utf8.ValidString(value) || length < tenantCredentialMinLength || length > tenantCredentialMaxLength {
return fmt.Errorf("%s must contain 32-50 valid UTF-8 characters", name)
}
for _, character := range value {
if unicode.IsControl(character) {
return fmt.Errorf("%s must not contain control characters", name)
}
if !isSafeCredentialCharacter(character) {
return fmt.Errorf("%s must contain only ASCII letters, digits, '.', '_', '~', or '-'", name)
}
}
return nil
}
func isSafeCredentialCharacter(character rune) bool {
return character >= 'a' && character <= 'z' ||
character >= 'A' && character <= 'Z' ||
character >= '0' && character <= '9' ||
character == '.' || character == '_' || character == '~' || character == '-'
}View on GitHub (pinned to 5e758547a8)