{"record":{"id":"c38960930d043f3b","repo":"derailed/k9s","slug":"unexpected-object-type-t","errorCode":null,"errorMessage":"unexpected object type: %T","messagePattern":"unexpected object type: %T","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/view/custom_jump.go","lineNumber":120,"sourceCode":"\n\treturn nil\n}\n\n// fetchResourceObject retrieves the full resource object for templating.\nfunc fetchResourceObject(app *App, gvr *client.GVR, path string) (map[string]any, error) {\n\taccessor, err := dao.AccessorFor(app.factory, gvr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\to, err := accessor.Get(context.Background(), path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tu, ok := o.(*unstructured.Unstructured)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"unexpected object type: %T\", o)\n\t}\n\n\treturn u.Object, nil\n}\n\n// determineTargetNamespace determines which namespace to use for the target resource.\nfunc determineTargetNamespace(sourcePath, targetNSConfig string, sourceObj map[string]any) (string, error) {\n\tsourceNS, _ := client.Namespaced(sourcePath)\n\n\tswitch targetNSConfig {\n\tcase \"\":\n\t\t// Default: use the source resource's namespace\n\t\t// If source is cluster-scoped, use ClusterScope\n\t\tif client.IsClusterScoped(sourceNS) {\n\t\t\treturn client.ClusterScope, nil\n\t\t}\n\t\treturn sourceNS, nil\n\tcase \"all\":","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/view/custom_jump.go#L102-L138","documentation":"fetchResourceObject() calls accessor.Get(ctx, path) and asserts the result to *unstructured.Unstructured. Some registered DAOs return typed runtime objects (e.g. *corev1.Pod) instead of unstructured; when a custom jump's source GVR is backed by such a typed DAO, the assertion fails and returns this error. Note fetchResourceObject runs unconditionally at the top of customJump, so any typed-DAO source breaks all custom jumps from that resource.","triggerScenarios":"Defining a jump rule whose source is a resource whose DAO returns a typed object rather than unstructured — commonly core/typed resources like pods, nodes, or secrets depending on k9s version.","commonSituations":"Jump rules authored for pod->X or secret->Y navigation; k9s upgrades that converted a DAO from generic (unstructured) to typed; CRDs are safe (always unstructured), built-ins vary.","solutions":["Point the jump rule at a source GVR whose DAO returns unstructured data (most CRDs and generic resources)","Test with a different source kind to confirm the typed-DAO hypothesis (the %T in the message names the concrete type)","Upgrade k9s — newer builds handle typed objects via conversion or report this as a known limitation; file an issue with the %T value if it persists"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func toUnstructured(o runtime.Object) (*unstructured.Unstructured, error) {\n    if u, ok := o.(*unstructured.Unstructured); ok {\n        return u, nil\n    }\n    u := &unstructured.Unstructured{}\n    if err := runtime.DefaultUnstructuredConverter.FromUnstructured(\n        mustToMap(o), u.Object); err != nil {\n        return nil, fmt.Errorf(\"cannot convert %T to unstructured: %w\", o, err)\n    }\n    return u, nil\n}","tryCatchPattern":null,"preventionTips":["When extending fetchResourceObject, use the ok-form assertion and convert typed objects instead of failing","Author jump rules against CRDs/generic resources that always resolve to unstructured","Log the %T value — it identifies exactly which DAO needs a conversion path"],"tags":["kubernetes","k9s","type-assertion","custom-resource","jump"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}