{"record":{"id":"aca4db3f816a8fc3","repo":"kovidgoyal/kitty","slug":"unsupported-secret-backend-s-for-s-supported-ba","errorCode":null,"errorMessage":"Unsupported secret backend %s for %s. Supported backends: text","messagePattern":"Unsupported secret backend (.+?) for (.+?)\\. Supported backends: text","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kittens/ssh/config.go","lineNumber":39,"sourceCode":"\t\"github.com/bmatcuk/doublestar/v4\"\n\t\"golang.org/x/sys/unix\"\n)\n\nvar _ = fmt.Print\n\nfunc resolve_secret(key, val string) (string, error) {\n\tv := strings.TrimSpace(val)\n\tif v == \"\" {\n\t\treturn \"\", nil\n\t}\n\tif b, s, ok := strings.Cut(v, \":\"); ok {\n\t\tb = strings.ToLower(strings.TrimSpace(b))\n\t\ts = strings.TrimSpace(s)\n\t\tswitch b {\n\t\tcase \"text\":\n\t\t\treturn s, nil\n\t\tdefault:\n\t\t\treturn \"\", fmt.Errorf(\"Unsupported secret backend %s for %s. Supported backends: text\", b, key)\n\t\t}\n\t}\n\treturn \"\", fmt.Errorf(\"No secret backend specified for: %s\", key)\n}\n\nfunc resolve_secrets(c *Config, only_syntax bool) error {\n\t_ = only_syntax // this will be useful when using backends that require user interaction\n\tif r, err := resolve_secret(\"password\", c.Password); err != nil {\n\t\treturn err\n\t} else {\n\t\tc.Password = r\n\t}\n\tif r, err := resolve_secret(\"totp_secret\", c.Totp_secret); err != nil {\n\t\treturn err\n\t} else {\n\t\tc.Totp_secret = r\n\t}\n\treturn nil","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kittens/ssh/config.go#L21-L57","documentation":"resolve_secret parses secret specifications of the form backend:value; only the 'text' backend is implemented. Any other backend name (lowercased, trimmed) yields this error naming the backend and the config key (password, etc.). Called from resolve_secrets during ssh config parsing.","triggerScenarios":"Writing config like password: env:MY_SECRET or password: keychain:foo — any backend prefix other than text:.","commonSituations":"Users assuming env-var or OS keychain backends exist (they do not in this implementation); copying config from tools with richer secret backends.","solutions":["Use the text backend: password: text:my-secret-value","Note only 'text' is supported; external backends must be resolved before config is passed","Move secrets out of config files since text stores them in plaintext"],"exampleFix":"// before\npassword: \"env:MY_PASSWORD\"\n// after\npassword: \"text:hunter2\"","handlingStrategy":"validation","validationCode":"const validBackends = map[string]bool{\"text\": true}\nif !validBackends[backend] { /* reject config early */ }","typeGuard":"func isSupportedBackend(b string) bool { return strings.ToLower(strings.TrimSpace(b)) == \"text\" }","tryCatchPattern":null,"preventionTips":["Only use backend:value syntax with 'text'","Resolve external secret stores in your own code before passing config"],"tags":["config","secrets","validation","ssh"],"backgroundTag":"unsupported-secret-backend","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}