{"record":{"id":"eacbc005af469072","repo":"go-delve/delve","slug":"failed-to-remove-memlock-limit-try-running-with-c","errorCode":null,"errorMessage":"failed to remove memlock limit (try running with CAP_SYS_RESOURCE or as root): %w","messagePattern":"failed to remove memlock limit \\(try running with CAP_SYS_RESOURCE or as root\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/internal/ebpf/helpers.go","lineNumber":247,"sourceCode":"\tif len(ctx.parsedBpfEvents) == 0 {\n\t\treturn make([]RawUProbeParams, 0)\n\t}\n\n\tevents := make([]RawUProbeParams, len(ctx.parsedBpfEvents))\n\tcopy(events, ctx.parsedBpfEvents)\n\tctx.parsedBpfEvents = ctx.parsedBpfEvents[:0]\n\treturn events\n}\n\nfunc LoadEBPFTracingProgram(path string) (*EBPFContext, error) {\n\tvar (\n\t\tctx  EBPFContext\n\t\terr  error\n\t\tobjs traceObjects\n\t)\n\n\tif err = rlimit.RemoveMemlock(); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to remove memlock limit (try running with CAP_SYS_RESOURCE or as root): %w\", err)\n\t}\n\tctx.executable, err = link.OpenExecutable(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif err := loadTraceObjects(&objs, nil); err != nil {\n\t\treturn nil, err\n\t}\n\tctx.objs = &objs\n\n\tctx.bpfRingBuf, err = ringbuf.NewReader(objs.Events)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tctx.bpfArgMap = objs.ArgMap\n\tctx.paramInfo = make(map[dwarfTypeKey]paramMeta)","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/internal/ebpf/helpers.go#L229-L265","documentation":"LoadEBPFTracingProgram wraps the error returned by cilium/ebpf's rlimit.RemoveMemlock(), which raises the process RLIMIT_MEMLOCK limit so the eBPF program and its maps can be loaded into the kernel. Without this the kernel would refuse to allocate pinned/unpinned BPF map memory. Delve re-raises it with a hint that the process needs CAP_SYS_RESOURCE or root, because only privileged processes may raise the memlock limit on most kernels.","triggerScenarios":"Calling LoadEBPFTracingProgram (invoked when starting a tracee session with --ebpf) as an unprivileged user whose RLIMIT_MEMLOCK cannot be raised: no root, no CAP_SYS_RESOURCE, and a hard memlock ulimit that is too low (e.g. 'ulimit -l' small or systemd LimitMEMLOCK not raised).","commonSituations":"Running 'dlv trace --ebpf' as a normal user; running inside a container without --privileged or with dropped capabilities; CI runners where the test user lacks CAP_SYS_RESOURCE; systemd units without LimitMEMLOCK=infinity.","solutions":["Run delve with sudo or as root: 'sudo dlv trace --ebpf ...' or 'sudo go test -run TestTraceEBPF ./cmd/dlv'.","Grant the capability without full root: 'sudo setcap cap_sys_resource+ep <dlv-binary>' or add CAP_SYS_RESOURCE/CAP_BPF/CAP_PERFMON to the container.","Raise the memlock limit: 'ulimit -l unlimited' in the shell, or set LimitMEMLOCK=infinity in the systemd unit.","In Docker, run with --privileged (as the project's eBPF tests do) instead of a restricted container."],"exampleFix":"// before\ngo test -run TestTraceEBPF3 -count 1 ./cmd/dlv\n// error: failed to remove memlock limit ...\n// after\nsudo go test -run TestTraceEBPF3 -count 1 ./cmd/dlv","handlingStrategy":"try-catch","validationCode":"// Before starting an eBPF trace session, check privilege/limits:\nfunc canLoadEBPF() error {\n\tif os.Geteuid() == 0 {\n\t\treturn nil\n\t}\n\tvar lim unix.Rlimit\n\tif err := unix.Getrlimit(unix.RLIMIT_MEMLOCK, &lim); err != nil {\n\t\treturn err\n\t}\n\tif lim.Cur < 8<<20 { // eBPF maps typically need more than a small memlock\n\t\treturn fmt.Errorf(\"memlock limit %d too low; run as root or grant CAP_SYS_RESOURCE\", lim.Cur)\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"ctx, err := ebpf.LoadEBPFTracingProgram(path)\nif err != nil {\n\tif strings.Contains(err.Error(), \"failed to remove memlock limit\") {\n\t\treturn fmt.Errorf(\"eBPF tracing requires elevated privileges: re-run with sudo or grant CAP_SYS_RESOURCE: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Run eBPF-backed sessions/tests with sudo or in a --privileged container, as the project's own test docs recommend.","Set LimitMEMLOCK=infinity in systemd units and 'ulimit -l unlimited' in shells used for tracing.","Grant CAP_SYS_RESOURCE (plus CAP_BPF/CAP_PERFMON on newer kernels) to the delve binary or container rather than full root where possible.","Probe privilege/memlock limits at startup and fall back to breakpoint-based tracing when eBPF cannot load."],"tags":["ebpf","linux","permissions","capabilities"],"backgroundTag":"memlock-rlimit-permission-denied","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}