{"record":{"id":"2db6abaf59f37234","repo":"etcd-io/etcd","slug":"unexpected-creatednotify-in-delete","errorCode":null,"errorMessage":"unexpected createdNotify in delete","messagePattern":"unexpected createdNotify in delete","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/v3/op.go","lineNumber":295,"sourceCode":"\t\tpanic(\"unexpected lease in delete\")\n\tcase ret.limit != 0:\n\t\tpanic(\"unexpected limit in delete\")\n\tcase ret.rev != 0:\n\t\tpanic(\"unexpected revision in delete\")\n\tcase ret.sort != nil:\n\t\tpanic(\"unexpected sort in delete\")\n\tcase ret.serializable:\n\t\tpanic(\"unexpected serializable in delete\")\n\tcase ret.countOnly:\n\t\tpanic(\"unexpected countOnly in delete\")\n\tcase ret.minModRev != 0, ret.maxModRev != 0:\n\t\tpanic(\"unexpected mod revision filter in delete\")\n\tcase ret.minCreateRev != 0, ret.maxCreateRev != 0:\n\t\tpanic(\"unexpected create revision filter in delete\")\n\tcase ret.filterDelete, ret.filterPut:\n\t\tpanic(\"unexpected filter in delete\")\n\tcase ret.createdNotify:\n\t\tpanic(\"unexpected createdNotify in delete\")\n\t}\n\treturn ret\n}\n\n// OpPut returns \"put\" operation based on given key-value and operation options.\nfunc OpPut(key, val string, opts ...OpOption) Op {\n\tret := Op{t: tPut, key: []byte(key), val: []byte(val)}\n\tret.applyOpts(opts)\n\tswitch {\n\tcase ret.end != nil:\n\t\tpanic(\"unexpected range in put\")\n\tcase ret.limit != 0:\n\t\tpanic(\"unexpected limit in put\")\n\tcase ret.rev != 0:\n\t\tpanic(\"unexpected revision in put\")\n\tcase ret.sort != nil:\n\t\tpanic(\"unexpected sort in put\")\n\tcase ret.serializable:","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/etcd-io/etcd/blob/f744d457f484e9f748a0700b48ef96dcf792df33/client/v3/op.go#L277-L313","documentation":"OpDelete rejects WithCreatedNotify. createdNotify asks a watch to emit a synthetic event when the watch is established; it has no meaning for a delete operation. After applyOpts sets ret.createdNotify, the final validation case panics with \"unexpected createdNotify in delete\".","triggerScenarios":"clientv3.OpDelete(k, clientv3.WithCreatedNotify()); copy-pasting a Watch option list into the cleanup Delete of a watch-based component; generic option forwarding from watch setup into teardown.","commonSituations":"Watch lifecycle code: the same helper that builds watch options (WithCreatedNotify, WithProgressNotify, WithPrevKey) is reused for deleting the watched key on shutdown; config bundles applied to all clientv3 calls.","solutions":["Remove WithCreatedNotify from Delete calls; it is exclusively a Watch option.","Keep watch-construction options in a separate slice from mutation options."],"exampleFix":"// before\n_, err := cli.Delete(ctx, watchedKey, clientv3.WithCreatedNotify()) // panics\n\n// after\n_, err := cli.Delete(ctx, watchedKey)","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["WithCreatedNotify is a Watch-only option; strip watch options before calling Delete/Put.","In watch-lifecycle components, maintain distinct option slices for watch setup vs key teardown.","Any 'unexpected X in delete/put' panic means a read/watch option leaked into a write path."],"tags":["go","etcd","clientv3","delete","watch","created-notify","panic","invalid-option"],"backgroundTag":null,"analyzedSha":"f744d457f484e9f748a0700b48ef96dcf792df33","analyzedAt":"2026-08-15T09:39:50.079Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}