iflytek/astron-agent · error
credential file is unavailable
Error message
credential file is unavailable
What it means
openCredentialFileNoFollow is the portability fallback used on platforms lacking O_NOFOLLOW. It Lstat's the credential path first and fails with 'credential file is unavailable' when the path itself cannot be stated — i.e. the file does not exist or is otherwise inaccessible to lstat. Production Unix images use the O_NOFOLLOW implementation instead.
Solutions
- Confirm the *_FILE environment variable points to an existing, correctly mounted path
- Check that the secret volume mounted successfully in the container (kubectl describe pod / docker inspect)
- Fix the path typo or create/restore the credential file, then restart the service
Example fix
// before TENANT_KEY_FILE=/secrets/tenant.key # file not mounted // after # mount the secret at /secrets and verify: ls -l /secrets/tenant.key TENANT_KEY_FILE=/secrets/tenant.key
Defensive patterns
Strategy: validation
Validate before calling
if info, err := os.Lstat(path); err != nil {
return fmt.Errorf("credential file %s missing/unavailable: %w", path, err)
} Try / catch
if _, err := config.LoadTenantBootstrapCredentials(ctx); err != nil {
if strings.Contains(err.Error(), "unavailable") {
logger.Fatal("credential file path not mounted; check *_FILE env and volume mounts")
}
return err
} Prevention
- Verify *_FILE paths exist in the container entrypoint before startup
- Ensure secret volumes mount successfully (check pod events)
- Keep credential paths consistent between manifests and code
When it happens
Trigger: credentialFromEnvironmentOrFile resolves a *_FILE env var, openCredentialFileNoFollow calls os.Lstat(fileName), and the path is missing (ENOENT), a broken symlink target, or lstat is denied by permissions.
Common situations: The *_FILE env var points at a path never mounted into the container, the secret volume failed to mount, a typo in the file path, or the credential file was deleted before startup.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- TENANT_KEY and TENANT_SECRET must be distinct values
- published legacy tenant credentials cannot be used
- credential file cannot be inspected
- credential file must be a regular non-symbolic-link file
- credential file is too large
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/7510a71112085875.
Report an issue: GitHub.
Appendix: source
Thrown at core/tenant/config/credential_file_other.go:15
//go:build !linux && !darwin
package config
import (
"errors"
"os"
)
// openCredentialFileNoFollow is a portability fallback for platforms without
// O_NOFOLLOW. Supported production images use the Unix implementation above.
func openCredentialFileNoFollow(fileName string) (*os.File, error) {
pathInfo, err := os.Lstat(fileName)
if err != nil {
return nil, errors.New("credential file is unavailable")
}
if pathInfo.Mode()&os.ModeSymlink != 0 || !pathInfo.Mode().IsRegular() {
return nil, errors.New(
"credential file must be a regular non-symbolic-link file",
)
}
file, err := os.Open(fileName)
if err != nil {
return nil, errors.New("credential file is unavailable")
}
openedInfo, err := file.Stat()
if err != nil || !openedInfo.Mode().IsRegular() || !os.SameFile(pathInfo, openedInfo) {
_ = file.Close()
return nil, errors.New("credential file changed while being opened")
}
return file, nil
}
View on GitHub (pinned to 5e758547a8)