iflytek/astron-agent · error

credential file cannot be read

Error message

credential file cannot be read

What it means

After the size checks pass, readCredentialFile reads the file with io.ReadAll(io.LimitReader(file, max+1)); if the read itself errors (I/O failure, decode issue on a pseudo-file), the raw error is replaced with this opaque message. It signals the file content could not be read from disk even though opening and stat succeeded.

Solutions

  1. Retry after confirming the credential file is stable on local disk
  2. Recreate the secret mount and restart the pod/service
  3. Check container/storage logs for underlying I/O errors at that path
Defensive patterns

Strategy: retry

Validate before calling

f, err := os.Open(path)
if err != nil { return err }
_, err = io.ReadAll(io.LimitReader(f, 4096))
if err != nil { return fmt.Errorf("credential path %s unreadable: %w", path, err) }
f.Close()

Try / catch

creds, err := config.LoadTenantBootstrapCredentials(ctx)
if err != nil {
    if strings.Contains(err.Error(), "cannot be read") {
        return backoff.Retry(func() error { _, err = config.LoadTenantBootstrapCredentials(ctx); return err }, policy)
    }
    return err
}

Prevention

When it happens

Trigger: credentialFromEnvironmentOrFile -> readCredentialFile: io.ReadAll on the opened credential file returns an error, e.g. the file vanished mid-read, a FUSE/network filesystem I/O error, or reading from a special file that returns errors.

Common situations: Secret volume being remounted during rollout, flaky network storage, or the path pointing to a procfs/sysfs pseudo-file that cannot be read in the container context.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

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

	}
	defer func() {
		_ = file.Close()
	}()

	openedInfo, err := file.Stat()
	if err != nil {
		return "", errors.New("credential file cannot be inspected")
	}
	if !openedInfo.Mode().IsRegular() {
		return "", errors.New("credential file must be a regular non-symbolic-link file")
	}
	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)

View on GitHub (pinned to 5e758547a8)