iflytek/astron-agent · error

must not contain control characters

Error message

%s must not contain control characters

What it means

After the length/UTF-8 check, validateCredential iterates the value and rejects any control character (unicode.IsControl), such as \n, \r, or \t. The credential is placed in HTTP headers and storage, so embedded control characters are forbidden. The message names which variable (TENANT_KEY or TENANT_SECRET) contained them.

Solutions

  1. Rewrite the secret file without trailing newline/control chars: printf '%s' "$VALUE" > file (use printf, not echo).
  2. Convert CRLF to LF: dos2unix on the secret file, or regenerate it on Linux.
  3. Ensure the secret is a single line with only ASCII letters, digits, and . _ ~ - characters.
  4. If the value legitimately contained newlines, it is the wrong secret — retrieve the correct single-line credential.

Example fix

// before
echo "$TENANT_KEY" > /run/secrets/tenant-key   # adds trailing \n

// after
printf '%s' "$TENANT_KEY" > /run/secrets/tenant-key
Defensive patterns

Strategy: validation

Validate before calling

func hasControlChars(v string) bool {
	for _, r := range v {
		if unicode.IsControl(r) { return true }
	}
	return false
}

Prevention

When it happens

Trigger: A credential value read from a file or pasted into an env var contains a trailing/interior newline, carriage return (Windows CRLF), tab, or other control byte, and validateCredential reaches the control-character branch.

Common situations: Secret file created on Windows with CRLF line endings; echo instead of printf -n when writing the secret file; multi-line paste into a Kubernetes Secret; YAML block scalar (|) adding a trailing newline (though readCredentialFile trims edges, interior newlines still fail).

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/ad7786d24b92e46a. Report an issue: GitHub.

Appendix: source

Thrown at core/tenant/config/bootstrap_credentials.go:143

	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)