{"record":{"id":"55e3ac1b8c4c060b","repo":"t8y2/dbx","slug":"lease-ttl-and-preservelease-cannot-be-specified","errorCode":null,"errorMessage":"lease, ttl, and preserveLease cannot be specified together","messagePattern":"lease, ttl, and preserveLease cannot be specified together","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/etcd-go/kv.go","lineNumber":250,"sourceCode":"\t\treturn nil, err\n\t}\n\tkey, err := keyBytesParam(params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvalue, err := parseValueObject(rawObject(params, \"value\"))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\texpectedModRevision := longOrNull(params, \"expectedModRevision\")\n\texpectedCreateRevision := longOrNull(params, \"expectedCreateRevision\")\n\tleaseValue := longOrNull(params, \"lease\")\n\tttlValue := longOrNull(params, \"ttl\")\n\tpreserveLease := boolOrDefault(params, \"preserveLease\", false)\n\thasLease := leaseValue != nil\n\thasTtl := ttlValue != nil\n\tif (hasLease && hasTtl) || (preserveLease && (hasLease || hasTtl)) {\n\t\treturn nil, errors.New(\"lease, ttl, and preserveLease cannot be specified together\")\n\t}\n\n\tctx, cancel := s.beginOperation()\n\tdefer s.endOperation(cancel)\n\tif preserveLease {\n\t\trevision, err := putPreservingLease(client, ctx, key, value)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn map[string]any{\"revision\": longString(revision)}, nil\n\t}\n\n\tvar leaseID clientv3.LeaseID\n\tvar grantedLeaseID clientv3.LeaseID\n\tif hasTtl {\n\t\tif *ttlValue <= 0 {\n\t\t\treturn nil, errors.New(\"ttl must be a positive integer\")\n\t\t}","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/etcd-go/kv.go#L232-L268","documentation":"Input-validation error thrown by the put operation at kv.go:250. The etcd lease model for a put accepts exactly one lease source: an existing lease ID (lease), a fresh lease granted from a TTL (ttl), or preserving the key's current lease (preserveLease). Supplying more than one of these together is ambiguous, so the driver rejects the call before touching etcd.","triggerScenarios":"Any put call whose params include both lease and ttl; or preserveLease=true together with either lease or ttl.","commonSituations":"Template/config merging that accumulates lease options from multiple layers (default ttl plus explicit lease); migrating code from ttl-based puts to preserveLease and leaving the old parameter in place; copy-pasted option objects.","solutions":["Remove all but one of lease, ttl, preserveLease from the put params — keep exactly one lease strategy (or none for a permanent key).","If you want the key to keep its existing lease, pass preserveLease:true and drop lease/ttl.","If you need a fresh expiring key, pass ttl only and omit lease/preserveLease.","If attaching to a pre-granted lease, pass lease (the lease ID number) only."],"exampleFix":"// before\nput(session, key, value, { ttl: 60, preserveLease: true })\n// after\nput(session, key, value, { preserveLease: true })","handlingStrategy":"validation","validationCode":"function validatePutLeaseOptions(opts) {\n  const n = [opts.lease != null, opts.ttl != null, opts.preserveLease === true].filter(Boolean).length;\n  if (n > 1) throw new Error('specify at most one of lease, ttl, preserveLease');\n}","typeGuard":"function hasConflictingLeaseOptions(p) {\n  return (p.lease != null && p.ttl != null) || (p.preserveLease === true && (p.lease != null || p.ttl != null));\n}","tryCatchPattern":"try { return put(session, key, value, opts); }\ncatch (e) {\n  if (String(e).includes('cannot be specified together')) {\n    const { lease, ttl, ...rest } = opts;\n    return put(session, key, value, rest); // drop conflicting lease opts\n  }\n  throw e;\n}","preventionTips":["Centralize put option building so lease strategy is chosen in one place.","Never merge default lease options with user-supplied ones blindly.","Pick one idiom per call site: ttl for expiring keys, preserveLease for updates, lease for pre-granted IDs.","Add a unit test asserting conflicting combos are rejected."],"tags":["etcd","lease","validation","params"],"backgroundTag":"conflicting-lease-options","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}