{"record":{"id":"6932ab822221fcaa","repo":"argoproj/argo-workflows","slug":"object-v-is-not-an-unstructured","errorCode":null,"errorMessage":"object %+v is not an unstructured","messagePattern":"object %\\+v is not an unstructured","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/controller/controller.go","lineNumber":841,"sourceCode":"\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (wfc *WorkflowController) deleteOffloadedNodesForWorkflow(ctx context.Context, uid string, versions []string) error {\n\tworkflows, err := wfc.wfInformer.GetIndexer().ByIndex(indexes.UIDIndex, uid)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar wf *wfv1.Workflow\n\tlogger := logging.RequireLoggerFromContext(ctx)\n\tswitch l := len(workflows); l {\n\tcase 0:\n\t\tlogger.WithField(\"uid\", uid).Info(ctx, \"Workflow missing, probably deleted\")\n\tcase 1:\n\t\tun, ok := workflows[0].(*unstructured.Unstructured)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"object %+v is not an unstructured\", workflows[0])\n\t\t}\n\t\tkey := un.GetNamespace() + \"/\" + un.GetName()\n\t\twfc.workflowKeyLock.Lock(key)\n\t\tdefer wfc.workflowKeyLock.Unlock(key)\n\n\t\tobj, ok := wfc.getWorkflowByKey(ctx, key)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"failed to get workflow by key after locking\")\n\t\t}\n\t\tun, ok = obj.(*unstructured.Unstructured)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"object %+v is not an unstructured\", obj)\n\t\t}\n\t\twf, err = util.FromUnstructured(un)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n","sourceCodeStart":823,"sourceCodeEnd":859,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/controller/controller.go#L823-L859","documentation":"In deleteOffloadedNodesForWorkflow (workflow/controller/controller.go:841), the UID index lookup over the workflow informer returned exactly one object, but its dynamic type is not *unstructured.Unstructured. The informer cache is expected to hold unstructured objects, so this indicates an unexpected object type in the cache. It is a defensive type-assertion failure inside the offloaded-node-status GC.","triggerScenarios":"The workflow informer's indexer (UIDIndex) returned an object whose concrete type is not *unstructured.Unstructured — e.g. the informer was configured with a typed decoder or a test injected a *wfv1.Workflow instead of an unstructured object. Practically only reachable with a misconfigured informer or non-standard embedding.","commonSituations":"Custom controller builds or tests that wire the workflow informer to typed objects instead of unstructured ones; upstream client-go behavior changes in exotic setups.","solutions":["Verify the workflow informer is created with an unstructured decoder (unstructured scheme) as the stock controller does.","If you embed the controller, pass the same unstructured informer type the controller constructs for itself.","In tests, seed the indexer with *unstructured.Unstructured objects built via util.FromWorkflow, not typed *wfv1.Workflow."],"exampleFix":"// before (test seeding typed object)\nindexer.Add(&wfv1.Workflow{ObjectMeta: metav1.ObjectMeta{Name: \"wf\", Namespace: \"ns\"}})\n// after\nun, _ := util.ToUnstructured(&wfv1.Workflow{ObjectMeta: metav1.ObjectMeta{Name: \"wf\", Namespace: \"ns\"}})\nindexer.Add(un)","handlingStrategy":"type-guard","validationCode":"// Before relying on informer objects, verify cache contents\nif !isUnstructured(obj) { log.Fatalf(\"workflow informer cache holds non-unstructured object: %T\", obj) }","typeGuard":"func isUnstructured(obj any) bool {\n    _, ok := obj.(*unstructured.Unstructured)\n    return ok\n}","tryCatchPattern":"un, ok := workflows[0].(*unstructured.Unstructured)\nif !ok {\n    return fmt.Errorf(\"object %+v is not an unstructured\", workflows[0])\n}","preventionTips":["Always build the workflow informer with the unstructured decoder","In tests, seed indexer with util.ToUnstructured output, never typed *wfv1.Workflow","Diff custom informer wiring against upstream controller setup"],"tags":["kubernetes","type-assertion","informer","gc"],"backgroundTag":"unexpected-object-type-in-informer","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}