Skip to content

mg: E (new CAS) flag ignored when modifying an existing item #1301

Open

Description

@UWCSZhou

Describe the bug
Meta Get (mg) documents the E(token) flag as "use token as new CAS value if item is modified"(doc/protocol.txt:558, in the metaget flag list). In practice E is applied only when mg autovivifies a new item (N flag); when mg modifies an existing item — e.g. touches its TTL with T — the E override is parsed and then silently dropped, and the item keeps its old CAS. Either the modify path is missing the override, or E should not be listed for mg in the docs.

To Reproduce
Against a default instance (memcached -p 11311 -l 127.0.0.1), over nc. use_cas is on (default). Sequence and actual responses:

set foo 0 0 3
bar
STORED
mg foo c t
HD c2 t-1 // baseline: CAS=2, no TTL
mg foo T90 E555 c t
HD c2 t90 // T applied (TTL→90) but CAS is STILL 2, not 555
mg foo c t
HD c2 t90 // confirms CAS unchanged

// contrast — E IS honored when N autovivifies a NEW key:
mg newkey N90 E555 c t
HD c555 t90 W // created; CAS set to 555 by E
mg newkey c t
HD c555 t90 Z // confirms CAS=555

Expected: because T90 modified foo, E555 should set its CAS to 555, so the second mg foo c t should report c555. Actual: CAS stays c2 on the modify path; E works only on autovivify-create.

Versions affected: reproduced on 1.6.44 (latest at time of writing). The relevant code (E parsed for all meta cmds, applied only on the mg autovivify do_item_link, with no case 'E' in the existing-item flag loop) appears unchanged for many prior releases, so likely long-standing — not an upgrade regression.

Root cause pointer (in case useful): E is parsed into of.cas_id_in at proto_parser.c:593; applied on autovivify via do_item_link(it, hv, of.has_cas_in ? of.cas_id_in : get_cas_id()); but the existing-item flag loop in process_mget handles T/N/R/s/t/c/f with no case 'E', so no ITEM_set_cas on the modify path. The parser comment at proto_parser.c:593 scopes E to // ms, md, ma, which suggests the doc listing E under metaget may be the error.

System Information

  • OS/Distro: Ubuntu
  • Version of OS/distro: 24.04.4 LTS (kernel 6.17.0-35-generic, x86_64)
  • Version of memcached: 1.6.44
  • Hardware detail: 13th Gen Intel Core i7-1360P (16 cores)

Detail (please include!)
No crash/segfault — addr2line/core dump N/A.
Fresh default instance. Relevant stats settings:
STAT cas_enabled yes
STAT maxbytes 67108864
STAT item_size_max 1048576
STAT num_threads 4
STAT binding_protocol auto-negotiate
STAT hashpower_init 0
STAT verbosity 0
stats (post-repro, otherwise idle): version 1.6.44, pointer_size 64, curr_items 2, total_items 2, cmd_set 1. Full stats / stats items / stats slabs are all defaults and available on request.

Activity

  1. dormando commented on Jul 8, 2026

    @dormando
    Member

    Hi,

    Thanks for the report. The E flag is only supposed to update in scenarios where the CAS would normally update. So not just during autovivication but during any kind of SET. IE: If you do an ms restricted by the current CAS, you can set the new CAS. CAS doesn't normally update on a plain GET.

    What is your use case for updating the CAS value on a straight get?

  2. dormando commented on Jul 8, 2026

    @dormando
    Member

    Oh I misread about the touch case... I'll trace that out, but I don't think touch was ever supposed to update CAS. so my original answer still holds true for that particular case.

    The docs could certainly be updated to make E under mg more clear.

    I guess same question but reworded differently: is there a use case for needing the CAS updated on a touch?

  3. UWCSZhou commented on Jul 8, 2026

    @UWCSZhou
    Author

    Oh I misread about the touch case... I'll trace that out, but I don't think touch was ever supposed to update CAS. so my original answer still holds true for that particular case.

    The docs could certainly be updated to make E under mg more clear.

    I guess same question but reworded differently: is there a use case for needing the CAS updated on a touch?

    Hi @dormando, thanks for the fast and clear response!

    To answer directly: I don't have a production use case for updating CAS on a plain get or touch. This came from my newly designed fuzzing tool, which compares the implementation against protocol.txt, where E is listed under the Meta Get flags. The flags led me to expect it to apply whenever mg modifies an item (e.g., a T touch). Your framing — E only takes effect where a store would normally set the CAS (set/autovivify), and get/touch don't update CAS — makes complete sense, and the current behavior is self-consistent with that.

    So agreed, this is a docs-clarity thing rather than a code bug. A note under mg that E only takes effect when the request actually stores/creates the item (autovivify) — and has no effect on a plain fetch or T touch — would've saved me the confusion.

    Feel free to close the issue under that case. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions