{"record":{"id":"482d04eb11563ab4","repo":"moonD4rk/HackBrowserData","slug":"t-w","errorCode":null,"errorMessage":"%T: %w","messagePattern":"%T: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"masterkey/retriever.go","lineNumber":45,"sourceCode":"// ChainRetriever tries retrievers in order, first success wins (macOS V10: gcoredump→password→security).\ntype ChainRetriever struct {\n\tretrievers []Retriever\n}\n\nfunc NewChain(retrievers ...Retriever) Retriever {\n\treturn &ChainRetriever{retrievers: retrievers}\n}\n\nfunc (c *ChainRetriever) RetrieveKey(hints Hints) ([]byte, error) {\n\tvar errs []error\n\tfor _, r := range c.retrievers {\n\t\tkey, err := r.RetrieveKey(hints)\n\t\tif err == nil && len(key) > 0 {\n\t\t\treturn key, nil\n\t\t}\n\t\tif err != nil {\n\t\t\tlog.Debugf(\"retriever %T failed: %v\", r, err)\n\t\t\terrs = append(errs, fmt.Errorf(\"%T: %w\", r, err))\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"all retrievers failed: %w\", errors.Join(errs...))\n}\n","sourceCodeStart":27,"sourceCodeEnd":50,"githubUrl":"https://github.com/moonD4rk/HackBrowserData/blob/0503d04d7a8d0379d060268a74f1b149e5a0aad5/masterkey/retriever.go#L27-L50","documentation":"Inside the multi-retriever RetrieveKey loop, each individual retriever failure is wrapped as \"%T: %w\" (the retriever's concrete Go type plus the cause) before being collected. These wrapped errors are intermediate — they end up joined inside the final \"all retrievers failed\" error. The %T prefix tells you exactly which retriever type failed.","triggerScenarios":"Any retriever in the chain returning an error from RetrieveKey(hints); the error is logged at debug level and appended to errs for the final join.","commonSituations":"A KeychainPasswordRetriever with an empty password, a FileRetriever pointing at a missing file, or a platform retriever hitting a command/exec failure.","solutions":["Inspect the %T prefix in the joined error to identify the failing retriever type","Fix the root cause carried in the wrapped error (see the innermost message)","Remove or reorder the failing retriever if another retriever can supply the key","Enable debug logging to see per-retriever failures as they happen"],"exampleFix":"// before\nretrievers := []Retriever{NewFileRetriever(\"\")}\n// after\npath := \"key.bin\"\nif _, err := os.Stat(path); err != nil {\n\tlog.Fatalf(\"retriever file missing: %v\", err)\n}\nretrievers := []Retriever{NewFileRetriever(path)}","handlingStrategy":"try-catch","validationCode":"if len(retrievers) == 0 {\n\treturn errors.New(\"no retrievers configured\")\n}","typeGuard":"func isRetrieverError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"retrievers failed\")\n}","tryCatchPattern":"key, err := r.RetrieveKey(hints)\nif err != nil {\n\tlog.Printf(\"retriever %T failed: %v\", r, err)\n\tkey, err = fallback.RetrieveKey(hints)\n}","preventionTips":["Configure at least one known-good retriever for the target OS","Enable debug logging to catch per-retriever failures early","Test each retriever's RetrieveKey in isolation during setup"],"tags":["go","error-wrapping","retriever-chain"],"backgroundTag":"api-request-failed","analyzedSha":"0503d04d7a8d0379d060268a74f1b149e5a0aad5","analyzedAt":"2026-09-06T13:38:28.707Z","contentChangedAt":"2026-09-06T13:38:28.707Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}