{"record":{"id":"273442286c7e1e9e","repo":"iflytek/astron-agent","slug":"credential-file-cannot-be-read","errorCode":null,"errorMessage":"credential file cannot be read","messagePattern":"credential file cannot be read","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tenant/config/bootstrap_credentials.go","lineNumber":128,"sourceCode":"\t}\n\tdefer func() {\n\t\t_ = file.Close()\n\t}()\n\n\topenedInfo, err := file.Stat()\n\tif err != nil {\n\t\treturn \"\", errors.New(\"credential file cannot be inspected\")\n\t}\n\tif !openedInfo.Mode().IsRegular() {\n\t\treturn \"\", errors.New(\"credential file must be a regular non-symbolic-link file\")\n\t}\n\tif openedInfo.Size() > maxCredentialFileBytes {\n\t\treturn \"\", errors.New(\"credential file is too large\")\n\t}\n\n\tdata, err := io.ReadAll(io.LimitReader(file, maxCredentialFileBytes+1))\n\tif err != nil {\n\t\treturn \"\", errors.New(\"credential file cannot be read\")\n\t}\n\tif len(data) > maxCredentialFileBytes {\n\t\treturn \"\", errors.New(\"credential file is too large\")\n\t}\n\treturn strings.TrimSpace(string(data)), nil\n}\n\nfunc validateCredential(name, value string) error {\n\tlength := utf8.RuneCountInString(value)\n\tif !utf8.ValidString(value) || length < tenantCredentialMinLength || length > tenantCredentialMaxLength {\n\t\treturn fmt.Errorf(\"%s must contain 32-50 valid UTF-8 characters\", name)\n\t}\n\tfor _, character := range value {\n\t\tif unicode.IsControl(character) {\n\t\t\treturn fmt.Errorf(\"%s must not contain control characters\", name)\n\t\t}\n\t\tif !isSafeCredentialCharacter(character) {\n\t\t\treturn fmt.Errorf(\"%s must contain only ASCII letters, digits, '.', '_', '~', or '-'\", name)","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/tenant/config/bootstrap_credentials.go#L110-L146","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Retry after confirming the credential file is stable on local disk","Recreate the secret mount and restart the pod/service","Check container/storage logs for underlying I/O errors at that path"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"f, err := os.Open(path)\nif err != nil { return err }\n_, err = io.ReadAll(io.LimitReader(f, 4096))\nif err != nil { return fmt.Errorf(\"credential path %s unreadable: %w\", path, err) }\nf.Close()","typeGuard":null,"tryCatchPattern":"creds, err := config.LoadTenantBootstrapCredentials(ctx)\nif err != nil {\n    if strings.Contains(err.Error(), \"cannot be read\") {\n        return backoff.Retry(func() error { _, err = config.LoadTenantBootstrapCredentials(ctx); return err }, policy)\n    }\n    return err\n}","preventionTips":["Mount secrets on reliable local volumes","Use atomic writes (temp file + rename) for credential updates","Retry transient I/O at startup with backoff"],"tags":["filesystem","credentials","io"],"backgroundTag":"file-read-failed","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}