{"record":{"id":"d82d94e75a74c8d9","repo":"hashicorp/nomad","slug":"svpreapply-unexpected-varop-received-q","errorCode":null,"errorMessage":"svPreApply: unexpected VarOp received: %q","messagePattern":"svPreApply: unexpected VarOp received: %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/variables_endpoint.go","lineNumber":191,"sourceCode":"\n\thasPerm := func(perm string) bool {\n\t\treturn aclObj.AllowVariableOperation(namespace,\n\t\t\tpath, perm, nil)\n\t}\n\n\tswitch op {\n\tcase structs.VarOpSet, structs.VarOpCAS, structs.VarOpLockAcquire,\n\t\tstructs.VarOpLockRelease:\n\t\tif !hasPerm(acl.VariablesCapabilityWrite) {\n\t\t\treturn structs.ErrPermissionDenied\n\t\t}\n\n\tcase structs.VarOpDelete, structs.VarOpDeleteCAS:\n\t\tif !hasPerm(acl.VariablesCapabilityDestroy) {\n\t\t\treturn structs.ErrPermissionDenied\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"svPreApply: unexpected VarOp received: %q\", op)\n\t}\n\n\treturn nil\n}\n\nfunc canonicalizeAndValidate(args *structs.VariablesApplyRequest) error {\n\n\tswitch args.Op {\n\tcase structs.VarOpLockAcquire:\n\t\t// In case the user wants to use the default values so no lock data was provided.\n\t\tif args.Var.VariableMetadata.Lock == nil {\n\t\t\targs.Var.VariableMetadata.Lock = &structs.VariableLock{}\n\t\t}\n\n\t\targs.Var.Canonicalize()\n\n\t\terr := args.Var.ValidateForLock()\n\t\tif err != nil {","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/variables_endpoint.go#L173-L209","documentation":"hasOperationPermissions maps each VarOp to the ACL capability required (list/write/destroy). If Apply receives an op outside the known set, no ACL case matches and the code returns this internal inconsistency error. It means an unrecognized VarOp reached permission checking — a programming or wire-format issue, not an operator action.","triggerScenarios":"Calling Variables Apply with an Op value that is not VarOpSet/VarOpCAS/VarOpDelete/VarOpDeleteCAS/VarOpLockAcquire/VarOpLockRelease — e.g. an invalid string deserialized into VarOpType, or a newer client op against an older server.","commonSituations":"Hand-crafted API requests with a misspelled op; version skew where a new operation type is sent to an older server; SDK misuse passing an empty Op.","solutions":["Set Op to a valid VarOpType (set, cas, delete, delete-cas, lock-acquire, lock-release)","Ensure client and server Nomad versions match if using newly added operations","Validate the op value in client code before calling Apply","Update the Nomad server if a newer client introduces unknown ops"],"exampleFix":"// before\nreq := &api.VariablesApplyRequest{Op: api.VarOpType(\"upsert\"), Var: v}\n\n// after\nreq := &api.VariablesApplyRequest{Op: api.VarOpSet, Var: v}","handlingStrategy":"validation","validationCode":"switch req.Op {\ncase api.VarOpSet, api.VarOpCAS, api.VarOpDelete, api.VarOpDeleteCAS, api.VarOpLockAcquire, api.VarOpLockRelease:\n    // ok\ndefault:\n    return fmt.Errorf(\"unsupported VarOp %q\", req.Op)\n}","typeGuard":"func isValidVarOp(op api.VarOpType) bool {\n    switch op {\n    case api.VarOpSet, api.VarOpCAS, api.VarOpDelete, api.VarOpDeleteCAS, api.VarOpLockAcquire, api.VarOpLockRelease:\n        return true\n    }\n    return false\n}","tryCatchPattern":"_, err := client.Variables().Apply(req, nil)\nif err != nil && strings.Contains(err.Error(), \"unexpected VarOp\") {\n    // fix op value or align client/server versions\n}","preventionTips":["Only use named VarOp constants; never cast raw strings","Keep client and server Nomad versions in sync for new ops","Validate Op server-side expectations in SDK wrappers"],"tags":["nomad","variables","validation","acl","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}