{"record":{"id":"5f367c61d7b903cd","repo":"cloudreve/cloudreve","slug":"thumb-size-not-found","errorCode":null,"errorMessage":"thumb size not found","messagePattern":"thumb size not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/filemanager/driver/onedrive/client.go","lineNumber":27,"sourceCode":"\t\"github.com/cloudreve/Cloudreve/v4/pkg/credmanager\"\n\t\"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs\"\n\t\"github.com/cloudreve/Cloudreve/v4/pkg/logging\"\n\t\"github.com/cloudreve/Cloudreve/v4/pkg/setting\"\n\n\t\"github.com/cloudreve/Cloudreve/v4/pkg/request\"\n)\n\nvar (\n\t// ErrAuthEndpoint 无法解析授权端点地址\n\tErrAuthEndpoint = errors.New(\"failed to parse endpoint url\")\n\t// ErrInvalidRefreshToken 上传策略无有效的RefreshToken\n\tErrInvalidRefreshToken = errors.New(\"no valid refresh token in this policy\")\n\t// ErrDeleteFile 无法删除文件\n\tErrDeleteFile = errors.New(\"cannot delete file\")\n\t// ErrClientCanceled 客户端取消操作\n\tErrClientCanceled = errors.New(\"client canceled\")\n\t// Desired thumb size not available\n\tErrThumbSizeNotFound = errors.New(\"thumb size not found\")\n)\n\ntype Client interface {\n\tListChildren(ctx context.Context, path string) ([]FileInfo, error)\n\tMeta(ctx context.Context, id string, path string) (*FileInfo, error)\n\tCreateUploadSession(ctx context.Context, dst string, opts ...Option) (string, error)\n\tGetSiteIDByURL(ctx context.Context, siteUrl string) (string, error)\n\tGetUploadSessionStatus(ctx context.Context, uploadURL string) (*UploadSessionResponse, error)\n\tUpload(ctx context.Context, file *fs.UploadRequest) error\n\tSimpleUpload(ctx context.Context, dst string, body io.Reader, size int64, opts ...Option) (*UploadResult, error)\n\tDeleteUploadSession(ctx context.Context, uploadURL string) error\n\tBatchDelete(ctx context.Context, dst []string) ([]string, error)\n\tGetThumbURL(ctx context.Context, dst string) (string, error)\n\tOAuthURL(ctx context.Context, scopes []string) string\n\tObtainToken(ctx context.Context, opts ...Option) (*Credential, error)\n}\n\n// client OneDrive客户端","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/cloudreve/cloudreve/blob/20c95ad73f3a8bcb72887fea91ff31ab24fa1011/pkg/filemanager/driver/onedrive/client.go#L9-L45","documentation":"During OneDrive Credential.Refresh, the loader fails to fetch its own storage policy row via inventory StoragePolicyClient.GetPolicyByID(c.PolicyID) (oauth.go:93-98). The credential embeds the policy ID it was minted for; without the row, the OAuth endpoint, client id, secret, and redirect needed for the refresh cannot be read, and the wrapped database error is returned.","triggerScenarios":"The OneDrive storage policy was deleted from the admin panel while its credential still sits in the credential manager; database unreachable during refresh; PolicyID stale after a DB restore or migration; ent returning not-found for the cached row.","commonSituations":"Deleting an 'unused' OneDrive policy while background jobs still hold its credential; DB flaps during token refresh; restoring the DB from a backup taken before the policy was recreated with a new ID.","solutions":["Confirm the policy ID exists (admin → storage policies; check the credential's PolicyID)","If the policy is gone, evict/purge the stale credential from the credential manager instead of retrying","Check DB connectivity and ent logs for the underlying error","If the policy was recreated with a new ID, re-run the OneDrive OAuth flow to mint a credential for the new ID"],"exampleFix":"// before\npolicy, err := storagePolicyClient.GetPolicyByID(ctx, c.PolicyID)\nif err != nil {\n\treturn nil, fmt.Errorf(\"failed to get storage policy: %w\", err)\n}\n\n// after — distinguish a missing policy so the caller can evict the credential\npolicy, err := storagePolicyClient.GetPolicyByID(ctx, c.PolicyID)\nif err != nil {\n\tif ent.IsNotFound(err) {\n\t\treturn nil, fmt.Errorf(\"storage policy %d no longer exists; revoke this credential: %w\", c.PolicyID, err)\n\t}\n\treturn nil, fmt.Errorf(\"failed to get storage policy %d: %w\", c.PolicyID, err)\n}","handlingStrategy":"validation","validationCode":"// Before scheduling a refresh, confirm the policy still exists\nif _, err := storagePolicyClient.GetPolicyByID(ctx, cred.PolicyID); ent.IsNotFound(err) {\n\t// evict the stale credential instead of retrying a doomed refresh\n\t_ = credManager.Delete(ctx, cred.Key())\n}","typeGuard":"func isPolicyMissing(err error) bool {\n\treturn ent.IsNotFound(err)\n}","tryCatchPattern":"if err != nil {\n\tif isPolicyMissing(err) {\n\t\t// evict credential, mark policy as needing re-auth; do not retry\n\t}\n\t// DB transient: retry refresh later\n\treturn nil, fmt.Errorf(\"failed to get storage policy: %w\", err)\n}","preventionTips":["Cascade-delete stored credentials when a storage policy is removed","Run a periodic consistency job between policies and the credential store","After DB restores, re-authenticate OneDrive policies whose IDs changed"],"tags":["onedrive","oauth","database","credential-refresh"],"backgroundTag":null,"analyzedSha":"20c95ad73f3a8bcb72887fea91ff31ab24fa1011","analyzedAt":"2026-08-16T01:42:55.403Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}