{"record":{"id":"81374e5fe1ace4d1","repo":"derailed/k9s","slug":"expecting-a-switchable-resource-81374e","errorCode":null,"errorMessage":"expecting a switchable resource","messagePattern":"expecting a switchable resource","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/view/context.go","lineNumber":156,"sourceCode":"\t\tapp.Flash().Err(err)\n\t\treturn\n\t}\n\tc.App().clearHistory()\n\tc.Refresh()\n\tc.GetTable().Select(1, 0)\n}\n\nfunc useContext(app *App, name string) error {\n\tif app.Content.Top() != nil {\n\t\tapp.Content.Top().Stop()\n\t}\n\tres, err := dao.AccessorFor(app.factory, client.CtGVR)\n\tif err != nil {\n\t\treturn err\n\t}\n\tswitcher, ok := res.(dao.Switchable)\n\tif !ok {\n\t\treturn errors.New(\"expecting a switchable resource\")\n\t}\n\n\tapp.Config.K9s.ToggleContextSwitch(true)\n\tdefer app.Config.K9s.ToggleContextSwitch(false)\n\n\t// Save config prior to context switch...\n\tif err := app.Config.Save(true); err != nil {\n\t\tslog.Error(\"Fail to save config to disk\", slogs.Subsys, \"config\", slogs.Error, err)\n\t}\n\n\tif err := switcher.Switch(name); err != nil {\n\t\tslog.Error(\"Context switch failed during use command\", slogs.Error, err)\n\t\treturn err\n\t}\n\n\treturn app.switchContext(cmd.NewInterpreter(\"ctx \"+name), true)\n}\n","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/view/context.go#L138-L174","documentation":"Returned by `useContext` (internal/view/context.go:~156), the handler for `:use <ctx>`. Exactly like the contextCmd path, it loads the DAO for `client.CtGVR` and asserts `dao.Switchable`; if the registered accessor lacks that interface the switch is aborted before the config is saved. In upstream k9s this cannot happen — the contexts DAO implements Switchable — so hitting it means a customized/broken DAO factory.","triggerScenarios":"Running `:use <context>` (or clicking through the context view) while the factory resolves client.CtGVR to an accessor that does not implement dao.Switchable.","commonSituations":"Forked builds or plugins replacing the contexts DAO; mocked factories in tests; version mismatch between internal packages after a partial upgrade.","solutions":["Restore/register the stock contexts DAO that implements dao.Switchable for client.CtGVR","In forks, implement Switch(ctx string) error on the custom contexts accessor","Alternatively switch contexts via KUBECONFIG + `--context` flag as a workaround while the factory is fixed"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func switchableFor(f dao.Factory) (dao.Switchable, error) {\n    a, err := dao.AccessorFor(f, client.CtGVR)\n    if err != nil {\n        return nil, err\n    }\n    s, ok := a.(dao.Switchable)\n    if !ok {\n        return nil, errors.New(\"expecting a switchable resource\")\n    }\n    return s, nil\n}","tryCatchPattern":"switcher, err := switchableFor(app.factory)\nif err != nil { return err }\nreturn switcher.Switch(name)","preventionTips":["Do not override the contexts DAO without implementing Switchable","Use KUBECONFIG/--context as an alternative context-switch path","Add a unit test asserting contexts accessor is Switchable"],"tags":["kubernetes","context-switch","dao","type-assertion","k9s"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}