iflytek/astron-agent · error
credential file must be a regular non-symbolic-link file
Error message
credential file must be a regular non-symbolic-link file
What it means
readCredentialFile requires the credential file to be a regular file and not a symbolic link; Stat()'s mode is checked and non-regular files (symlink, directory, fifo, device) are rejected. This prevents symlink-based attacks and accidental misconfiguration of the credential path.
Solutions
- Replace the symlink with a real regular file (copy the content, do not link)
- Mount the credential directly (e.g. Kubernetes secret volume files are fine — use the resolved path under ..data only via the mount)
- Verify with `stat -c %F <path>` that it reports 'regular file'
Example fix
# before ln -s /etc/tenant/secret.pem /creds/TENANT_SECRET # after cp /etc/tenant/secret.pem /creds/TENANT_SECRET && chmod 600 /creds/TENANT_SECRET
Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Lstat(path)
if err != nil || info.Mode()&os.ModeSymlink != 0 || !info.Mode().IsRegular() {
return fmt.Errorf("%s must be a regular file, not a symlink", path)
} Try / catch
if err := config.ValidateCredentialPaths(map[string]string{"TENANT_KEY_FILE": keyPath, "TENANT_SECRET_FILE": secretPath}); err != nil {
logger.Fatal("fix credential mounts: only regular files allowed")
} Prevention
- Never symlink credential files; copy or mount them directly
- Check mounts with `stat -c '%F %N'` during image/manifest review
- Keep credential directories (e.g. /creds) free of pipes and devices
When it happens
Trigger: credentialFromEnvironmentOrFile resolves a *_FILE env var to a path; the opened file's Stat().Mode() is not IsRegular() — e.g. the path is a symlink (including an attacked symlink to /etc/shadow) or a named pipe.
Common situations: Operator symlinked a credential file for convenience instead of mounting it directly, a tmpfs/fifo was used, or a container secret mount created an intermediate symlink.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- credential file must be a regular non-symbolic-link file
- Remote resource URL must not include user information
- Outbound URL must not include user information
- published legacy tenant credentials cannot be used
- credential file cannot be inspected
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/02bef6783211570c.
Report an issue: GitHub.
Appendix: source
Thrown at core/tenant/config/bootstrap_credentials.go:120
}
return value, nil
}
func readCredentialFile(fileName string) (string, error) {
file, err := openCredentialFileNoFollow(fileName)
if err != nil {
return "", err
}
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 {View on GitHub (pinned to 5e758547a8)