{"record":{"id":"5122a43123b97fc4","repo":"pocketbase/pocketbase","slug":"key-s-w","errorCode":null,"errorMessage":"[key: %s] %w","messagePattern":"\\[key: (.+?)\\] %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"tools/filesystem/blob/bucket.go","lineNumber":727,"sourceCode":"\treturn wrapError(b.drv, b.drv.Close(), \"\")\n}\n\nfunc wrapError(b Driver, err error, key string) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\n\t// don't wrap or normalize EOF errors since there are many places\n\t// in the standard library (e.g. io.ReadAll) that rely on checks\n\t// such as \"err == io.EOF\" and they will fail\n\tif errors.Is(err, io.EOF) {\n\t\treturn err\n\t}\n\n\terr = b.NormalizeError(err)\n\n\tif key != \"\" {\n\t\terr = fmt.Errorf(\"[key: %s] %w\", key, err)\n\t}\n\n\treturn err\n}\n","sourceCodeStart":709,"sourceCodeEnd":732,"githubUrl":"https://github.com/pocketbase/pocketbase/blob/5d217ddb50cb144d80a5d0b0bdf11b52b2c3e457/tools/filesystem/blob/bucket.go#L709-L732","documentation":"This is not a distinct failure but the portable blob package's error-wrapping step: when an operation fails and a key is known, the driver error is normalized (via NormalizeError / gcerrors) and prefixed with \"[key: <key>]\" using %w, so the original error stays unwrappable. Seeing this message means some underlying driver operation on that key failed; the real cause is the wrapped error.","triggerScenarios":"Any wrapped failure path in Bucket (Read, Write, Close, Copy, Delete, Attributes, List) where the helper is called with a non-empty key — e.g. driver returns NotFound, permission, or I/O error for that key. The io.EOF case is deliberately passed through unwrapped so stdlib checks like err == io.EOF keep working.","commonSituations":"Developers see only the prefix in logs and misdiagnose it; the actual problem is the wrapped driver error (file missing, S3 403, connection reset). Also hit when string-matching errors instead of using errors.Is/errors.As and gcerrors.Code.","solutions":["Inspect the wrapped error: use errors.Is(err, target) / errors.As on the chain, or gcerrors.Code(err) to classify (NotFound, PermissionDenied, ...).","Reproduce the underlying driver failure directly (check the file/S3 resource for that key).","If you string-matched error text before, switch to gcerrors.Code-based handling."],"exampleFix":"// before\nif strings.Contains(err.Error(), \"not found\") { ... }\n\n// after\nif gcerrors.Code(err) == gcerrors.NotFound { ... }\n// or: if errors.Is(err, blob.ErrObjectNotFound) { ... }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isBlobNotFound(err error) bool { return gcerrors.Code(err) == gcerrors.NotFound }","tryCatchPattern":"if err := bucket.Read(...); err != nil {\n    switch gcerrors.Code(err) {\n    case gcerrors.NotFound:\n        // handle missing object\n    default:\n        // log full chain: err (already wraps driver cause with [key: ...])\n    }\n}","preventionTips":["Always branch on gcerrors.Code / errors.Is, never on message text.","Log the full error chain (err plus %v of wrapped cause) to see the driver-level reason.","Keep keys in log context separately; the [key: ...] prefix is a hint, not the diagnosis."],"tags":["go","blob","error-wrapping","diagnostics"],"backgroundTag":null,"analyzedSha":"5d217ddb50cb144d80a5d0b0bdf11b52b2c3e457","analyzedAt":"2026-08-15T10:06:33.165Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}