{"record":{"id":"a22b91feff78e915","repo":"cilium/cilium","slug":"s-preparecollection-s-w","errorCode":null,"errorMessage":"%s: PrepareCollection(): \\\"%s\\\": %w","messagePattern":"(.+?): PrepareCollection\\(\\): \\\\\"(.+?)\\\\\": %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/datapath/loader/plugins.go","lineNumber":344,"sourceCode":"\t\t\t\t\tlogfields.CiliumDatapathPluginName, r.plugin.Name(),\n\t\t\t\t\tlogfields.Error, r.err,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tcontinue\n\t\t} else {\n\t\t\tresponses[r.plugin.Name()] = r.resp\n\t\t}\n\n\tprocess_hooks:\n\t\tfor _, h := range r.resp.Hooks {\n\t\t\tps := spec.Programs[h.Target]\n\t\t\tif ps == nil {\n\t\t\t\terr = errors.Join(err, fmt.Errorf(\"%s: PrepareCollection(): target program \\\"%s\\\" does not exist in the collection spec\", r.plugin.Name(), h.Target))\n\n\t\t\t\tcontinue\n\t\t\t} else if canErr := canInstrument(ps, attachmentContext); canErr != nil {\n\t\t\t\terr = errors.Join(err, fmt.Errorf(\"%s: PrepareCollection(): \\\"%s\\\": %w\", r.plugin.Name(), h.Target, canErr))\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif h.Type != datapathplugins.HookType_PRE && h.Type != datapathplugins.HookType_POST {\n\t\t\t\terr = errors.Join(err, fmt.Errorf(\"%s: PrepareCollection(): invalid hook type %v\", r.plugin.Name(), h.Type))\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\thooksSpec.hook(ps.Name, h.Type).addNode(r.plugin.Name())\n\n\t\t\tfor _, c := range h.Constraints {\n\t\t\t\totherPlugin := lnc.Plugins[c.Plugin]\n\t\t\t\tif otherPlugin == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/datapath/loader/plugins.go#L326-L362","documentation":"For each hook a plugin requests, prepareCollection calls canInstrument(ps, attachmentContext) to check the program is instrumentable in this attachment context (type/attach-type/section constraints). A failed check is recorded as '<plugin>: PrepareCollection(): \"X\": <reason>' and fails the load.","triggerScenarios":"A plugin requests a hook on a program that exists in the spec but canInstrument rejects it for this attachmentContext — e.g. hooking a program type not allowed for that context, attaching to a socket-load or unrelated program section, or an attachment kind the program doesn't support.","commonSituations":"Plugin registered for endpoint attachments tries to hook host-netdev-only programs; plugin not updated after the datapath moved a program to a different section/type; plugin enabled globally but only valid for specific attachment kinds.","solutions":["Read the wrapped canInstrument reason and restrict the plugin to the attachment contexts it supports","Update the plugin so its hook targets match programs instrumentable in this context","Adjust the plugin's registration/configuration so it is only loaded for valid attachment kinds","If the hook is optional, switch the plugin to a best-effort AttachmentPolicy","Update the datapath program's section/type if it was unintentionally changed"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func canAttachToContext(ps *ebpf.ProgramSpec, ctx *AttachmentContext) error {\n    switch ctx.Kind {\n    case AttachmentEndpoint:\n        if !endpointInstrumentable(ps) { return fmt.Errorf(\"program %q not instrumentable for endpoints\", ps.Name) }\n    case AttachmentHost:\n        if !hostInstrumentable(ps) { return fmt.Errorf(\"program %q not instrumentable for host netdev\", ps.Name) }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register plugins only for the attachment kinds whose programs they hook","Keep plugin hook targets within programs whose sections/types canInstrument allows","Test plugin+agent integration per attachment kind in CI","Re-check canInstrument rules when moving programs between sections"],"tags":["ebpf","plugin","datapath","validation"],"backgroundTag":"plugin-hook-not-instrumentable","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}