diff --git a/src/AlarmHandler.cpp b/src/AlarmHandler.cpp
index 0acebd46d6e38141a96e1e3cc786dc1d75c95700..35c3d0b5b3fc81ecf47728f9903271ac3c08a2b4 100644
--- a/src/AlarmHandler.cpp
+++ b/src/AlarmHandler.cpp
@@ -1922,13 +1922,13 @@ Tango::DevVarStringArray *AlarmHandler::search_alarm(Tango::DevString argin)
 		start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
 	}*/
 	start_pos = filter.find("*", start_pos);
-	if(start_pos != std::string::npos && start_pos == filter.size()-1) //* is the only character or at the end of the filter
+	if(start_pos != std::string::npos && start_pos == filter.size()-1) // * is the only character or at the end of the filter
 	{
 		filter.replace(start_pos, 1, "");
 		filter_begin = filter;
 		DEBUG_STREAM << __func__ << ": updated filter to: " << filter_begin;
 	}
-	/*else if(start_pos != std::string::npos) //* is in the middle of the filter
+	/*else if(start_pos != std::string::npos) // * is in the middle of the filter
 	{
 		string filter_begin=filter.substr(0,start_pos);
 		string filter_end=filter.substr(start_pos+1);
@@ -3657,6 +3657,7 @@ void AlarmHandler::do_alarm(bei_t& e)
 		}
 		if(found_ev != events->v_event.end())
 		{
+			found_ev->valid = false;
 			Tango::TimeVal ts = gettime();
 			found_ev->err_counter++;
 			if(e.type == TYPE_TANGO_ERR)
@@ -3675,10 +3676,15 @@ void AlarmHandler::do_alarm(bei_t& e)
 			list<string>::iterator j = m_alarm.begin();
 			while (j != m_alarm.end())
 			{
+				DEBUG_STREAM << "AlarmHandler::"<<__func__<<": before do_alarm_eval name=" << *j << " ev=" << e.ev_name << " err=" << found_ev_ex_desc << endl;
+				changed = do_alarm_eval(*j, e.ev_name, ts);
+				//if(!changed)
+				//	continue;	//TODO: check if OK
 				alarms.vlock->readerIn();
 				alarm_container_t::iterator it = alarms.v_alarm.find(*j);
 				if(it != alarms.v_alarm.end())
 				{
+#if 0 //already done in alarm_table::update called by do_alarm_eval
 					it->second.err_counter++;
 					//if first error, reset ACK
 					if(it->second.ex_reason.empty() && it->second.ex_desc.empty() && it->second.ex_origin.empty())
@@ -3712,8 +3718,11 @@ void AlarmHandler::do_alarm(bei_t& e)
 						}
 						it->second.error = true;
 					}
+#endif
 					alarm_t alm = it->second;
 					alarms.vlock->readerOut();
+					DEBUG_STREAM << "AlarmHandler::"<<__func__<<": after do_alarm_eval name=" << *j << " error=" << (int)alm.error << " enabled=" << alm.enabled << endl;
+#if 0 //TODO: already pushed in do_alarm_eval, not necessary here ?
 					if(alm.error && alm.enabled && !(alm.shelved && alm.silenced > 0))
 					{
 						try
@@ -3731,7 +3740,7 @@ void AlarmHandler::do_alarm(bei_t& e)
 						}catch(Tango::DevFailed &ex)
 						{}
 					}
-					else
+					else if(alm.error) //TODO: or if(changed) ?
 					{
 						Tango::DevEnum *attr_value = get_AlarmState_data_ptr(alm.attr_name);
 						if(!alm.enabled)
@@ -3755,6 +3764,7 @@ void AlarmHandler::do_alarm(bei_t& e)
 							push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
 						}
 					}
+#endif
 				}
 				else
 				{
@@ -3805,7 +3815,6 @@ void AlarmHandler::do_alarm(bei_t& e)
 		return;
 	}	
 	DEBUG_STREAM << "AlarmHandler::"<<__func__<<": arrived event=" << e.ev_name << endl;
-	formula_res_t res;
 	events->veclock.readerIn();
 	vector<event>::iterator found = \
 			find(events->v_event.begin(), events->v_event.end(), e.ev_name);
@@ -3973,10 +3982,10 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
 			it->second.to_be_evaluated = false;
 			it->second.attr_values.erase(it->second.attr_values.size()-1);
 			it->second.attr_values += string("}");
-			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << res.value << " quality=" << res.quality << endl;
+			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << res.value << " quality=" << res.quality << " valid=" << (int)res.valid << endl;
 			changed = alarms.update(tmpname, ts, res, it->second.attr_values, it->second.grp2str(), it->second.msg, it->second.formula); 		//update internal structure and log to db
-			changed = changed || prev_error;
-			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << endl;
+			changed = changed || (prev_error && res.valid);
+			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << " error=" << (int)it->second.error << endl;
 			Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
 			if(!it->second.enabled)
 				*attr_value = _OOSRV;
@@ -4442,7 +4451,18 @@ void AlarmHandler::set_internal_alarm(string name, Tango::TimeVal t, string msg,
 //==============================================================
 formula_res_t AlarmHandler::eval_formula(tree_parse_info_t tree, string &attr_values)
 {
-    return eval_expression(tree.trees.begin(), attr_values);
+	formula_res_t res = eval_expression(tree.trees.begin(), attr_values);
+#ifdef _DEBUG_FORMULA
+	DEBUG_STREAM << __func__ << ": 		 finally value=" << res.value << " valid=" << (int)res.valid << " error='" << res.error << "' ex_desc='" << res.ex_desc<<"'" << endl;
+#endif
+	if(res.valid)
+	{
+		res.ex_reason.clear();
+		res.ex_desc.clear();
+		res.ex_origin.clear();
+		res.error.clear();
+	}
+    return res;
 }
 
 formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, int ev_ind) //throw (string &), std::out_of_range
@@ -4462,6 +4482,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
         string val_d(i->value.begin(), i->value.end());
 		formula_res_t res;
 		res.value = strtod(val_d.c_str(), 0);
+		res.valid = true;
 #ifdef _DEBUG_FORMULA
 		DEBUG_STREAM << "		node value real = " << val_d << "(value="<<res.value<<" quality="<<res.quality<<")" << endl;
 #endif
@@ -4480,6 +4501,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 #endif
 		formula_res_t res;
 		res.value = strtod(val_d.c_str(), 0);
+		res.valid = true;
         return res;
     } 
     else if (i->value.id() == formula_grammar::val_stID)
@@ -4496,6 +4518,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 #endif
 		formula_res_t res;
 		res.value = st;
+		res.valid = true;
         return res;
     }
     else if (i->value.id() == formula_grammar::val_alarm_enum_stID)
@@ -4512,6 +4535,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 #endif
 		formula_res_t res;
 		res.value = st;
+		res.valid = true;
         return res;
     }
 	else if (i->value.id() == formula_grammar::val_qualityID)
@@ -4529,6 +4553,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 #endif
 		formula_res_t res;
 		res.value = quality;
+		res.valid = true;
         return res;
 	}
     else if (i->value.id() == formula_grammar::unary_exprID)
@@ -4685,8 +4710,19 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 					err << it->ex_desc << "";
 				else
 					err <<  "attribute " << string(i->value.begin(), i->value.end()) << " value not valid while evaluating formula";
+				formula_res_t res;
+				res.valid = false;
+				res.quality = it->quality;
+				res.ex_reason = it->ex_reason;
+				res.ex_desc = it->ex_desc;
+				res.ex_origin = it->ex_origin;
+				res.error = err.str();
+#ifdef _DEBUG_FORMULA
+				DEBUG_STREAM << "		attribute -> " << string(i->value.begin(), i->value.end()) << " value not valid, desc=" << res.ex_desc << endl;
+#endif
 				events->veclock.readerOut();
-        		throw err.str();
+        		//throw err.str();
+				return res;
         	}	
 			else if(it->type != Tango::DEV_STRING && it->value.empty())
 			{
@@ -4694,8 +4730,19 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 					err << it->ex_desc << "";
 				else
 					err <<  "attribute " << string(i->value.begin(), i->value.end()) << " value not initialized while evaluating formula";
+				formula_res_t res;
+				res.valid = false;
+				res.quality = it->quality;
+				res.ex_reason = it->ex_reason;
+				res.ex_desc = it->ex_desc;
+				res.ex_origin = it->ex_origin;
+				res.error = err.str();
+#ifdef _DEBUG_FORMULA
+				DEBUG_STREAM << "		attribute -> " << string(i->value.begin(), i->value.end()) << " value empty, desc=" << res.ex_desc << endl;
+#endif
 				events->veclock.readerOut();
-        		throw err.str();
+        		//throw err.str();
+				return res;
         	}        	
 			ostringstream temp_attr_val;
 			if(it->value.size() > 1)
@@ -4704,6 +4751,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 				temp_attr_val << "\"" <<  it->name << "\":" <<it->value.at(ev_ind) << ",";//throw  std::out_of_range
 			attr_values += temp_attr_val.str();
 			formula_res_t res;
+			res.valid = true;
 			res.quality = it->quality;
 			res.ex_reason = it->ex_reason;
 			res.ex_desc = it->ex_desc;
@@ -4734,6 +4782,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
      	DEBUG_STREAM << "		node index = " << val_d << endl;
 #endif
      	formula_res_t res;
+		res.valid = true;
      	res.value = strtod(val_d.c_str(), 0);
         return res;
     }   
@@ -4776,6 +4825,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 		formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
            	res_2=eval_expression(i->children.begin()+1, attr_values);
         long val_l1,val_l2;
+		bool valid = res_1.valid && res_2.valid;
             
     	string err2("ERROR: non-int value in bitwise operation!");
     	val_l1 = (long)trunc(res_1.value);		//transform to long
@@ -4788,30 +4838,42 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
         {
         	formula_res_t res;
         	res.value = (double)(val_l1 & val_l2);
+			res.valid = valid;
         	res.quality = res.combine_quality(res_1.quality, res_2.quality);
-        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
-        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
-        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
+				res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
+				res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			}
             return res;
         }
         else if (*i->value.begin() == '|')
         {      
         	formula_res_t res;
         	res.value = (double)(val_l1 | val_l2);
+			res.valid = valid;
         	res.quality = res.combine_quality(res_1.quality, res_2.quality);
-        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
-        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
-        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
+				res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
+				res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			}
             return res;
         }  
         else if (*i->value.begin() == '^')
         {
         	formula_res_t res;
         	res.value = (double)(val_l1 ^ val_l2);
+			res.valid = valid;
         	res.quality = res.combine_quality(res_1.quality, res_2.quality);
-        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
-        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
-        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
+				res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
+				res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			}
             return res;
         }  
         else
@@ -4833,6 +4895,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 		formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
            	res_2=eval_expression(i->children.begin()+1, attr_values);
         long val_l1,val_l2;
+		bool valid = res_1.valid && res_2.valid;
             
     	string err2("ERROR: non-int value in bitwise operation!");
     	val_l1 = (long)trunc(res_1.value);		//transform to long
@@ -4845,20 +4908,28 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
         {
         	formula_res_t res;
         	res.value = (double)(val_l1 << val_l2);
+			res.valid = valid;
         	res.quality = res.combine_quality(res_1.quality, res_2.quality);
-        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
-        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
-        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
+				res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
+				res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			}
             return res;
         }
         else if (string(i->value.begin(), i->value.end()) == string(">>"))
         {
         	formula_res_t res;
         	res.value = (double)(val_l1 >> val_l2);
+			res.valid = valid;
         	res.quality = res.combine_quality(res_1.quality, res_2.quality);
-        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
-        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
-        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
+				res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
+				res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			}
             return res;
         }  
         else
@@ -4918,6 +4989,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 					ostringstream temp_attr_val;
 					temp_attr_val << "\"" << it->name << "\":\"" <<it->value_string << "\",";
 					attr_values += temp_attr_val.str();
+					res.valid = true;
 					res.quality = it->quality;
 					res.ex_reason = it->ex_reason;
 					res.ex_desc = it->ex_desc;
@@ -5066,8 +5138,19 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 						err << it->ex_desc << "";
 					else
 						err <<  "attribute " << string(i->value.begin(), i->value.end()) << " value not valid while evaluating formula";
+					formula_res_t res;
+					res.valid = false;
+					res.quality = it->quality;
+					res.ex_reason = it->ex_reason;
+					res.ex_desc = it->ex_desc;
+					res.ex_origin = it->ex_origin;
+					res.error = err.str();
+#ifdef _DEBUG_FORMULA
+					DEBUG_STREAM << "		attribute -> " << string(i->value.begin(), i->value.end()) << " value not valid, desc=" << res.ex_desc << endl;
+#endif
 					events->veclock.readerOut();
-					throw err.str();
+					//throw err.str();
+					return res;
 				}
 				else if(it->type != Tango::DEV_STRING && it->value.empty())
 				{
@@ -5075,8 +5158,19 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 						err << it->ex_desc << "";
 					else
 						err <<  "attribute " << string(i->value.begin(), i->value.end()) << " value not initialized while evaluating formula";
+					formula_res_t res;
+					res.valid = false;
+					res.quality = it->quality;
+					res.ex_reason = it->ex_reason;
+					res.ex_desc = it->ex_desc;
+					res.ex_origin = it->ex_origin;
+					res.error = err.str();
+#ifdef _DEBUG_FORMULA
+					DEBUG_STREAM << "		attribute -> " << string(i->value.begin(), i->value.end()) << " value empty, desc=" << res.ex_desc << endl;
+#endif
 					events->veclock.readerOut();
-					throw err.str();
+					//throw err.str();
+					return res;
 				}     
 
 				ostringstream temp_attr_val;
@@ -5147,34 +5241,47 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 		}
 		formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
            	res_2=eval_expression(i->children.begin()+1, attr_values);
+		bool valid = res_1.valid && res_2.valid;
 		if (string(i->value.begin(), i->value.end()) == string("min"))
 		{
         	formula_res_t res;
         	res.value = min(res_1.value, res_2.value);
+			res.valid = valid;
         	res.quality = res.combine_quality(res_1.quality, res_2.quality);
-        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
-        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
-        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
+				res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
+				res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			}
             return res;
 		}
 		else if (string(i->value.begin(), i->value.end()) == string("max"))
 		{
         	formula_res_t res;
         	res.value = max(res_1.value, res_2.value);
+			res.valid = valid;
         	res.quality = res.combine_quality(res_1.quality, res_2.quality);
-        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
-        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
-        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
+				res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
+				res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			}
             return res;
 		}
 		else if (string(i->value.begin(), i->value.end()) == string("pow"))
 		{
         	formula_res_t res;
         	res.value = pow(res_1.value, res_2.value);
+			res.valid = valid;
         	res.quality = res.combine_quality(res_1.quality, res_2.quality);
-        	res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
-        	res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
-        	res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
+				res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
+				res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
+			}
             return res;
 		}
 		else
@@ -5217,6 +5324,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
     }
     formula_res_t res;
     res.value = 0;
+	res.valid = false;
     return res;
 }
 
@@ -5308,7 +5416,7 @@ void AlarmHandler::prepare_alarm_attr()
 		}
 		else
 		{
-			if(ai->second.stat == S_ALARM && ai->second.ack == ACK)
+			if(ai->second.stat == S_ALARM && ai->second.ack == ACK && !ai->second.error)
 			{
 				acknowledgedAlarms_read[acknowledgedAlarms_sz] = ai->second.name;
 				attr_alarmAcknowledged_read[acknowledgedAlarms_sz] = const_cast<char*>(acknowledgedAlarms_read[acknowledgedAlarms_sz].c_str());
@@ -5318,7 +5426,7 @@ void AlarmHandler::prepare_alarm_attr()
 				acknowledgedAlarms_sz++;
 				almstate = "ACKED";
 			}
-			else if(ai->second.stat == S_ALARM && ai->second.ack == NOT_ACK)
+			else if(ai->second.stat == S_ALARM && ai->second.ack == NOT_ACK && !ai->second.error)
 			{
 				unacknowledgedAlarms_read[unacknowledgedAlarms_sz] = ai->second.name;
 				attr_alarmUnacknowledged_read[unacknowledgedAlarms_sz] = const_cast<char*>(unacknowledgedAlarms_read[unacknowledgedAlarms_sz].c_str());
@@ -5328,7 +5436,7 @@ void AlarmHandler::prepare_alarm_attr()
 				unacknowledgedAlarms_sz++;
 				almstate = "UNACK";
 			}
-			else if(ai->second.stat == S_NORMAL && ai->second.ack == NOT_ACK)
+			else if(ai->second.stat == S_NORMAL && ai->second.ack == NOT_ACK && !ai->second.error)
 			{
 				unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz] = ai->second.name;
 				attr_alarmUnacknowledgedNormal_read[unacknowledgedNormalAlarms_sz] = const_cast<char*>(unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz].c_str());
@@ -5338,7 +5446,7 @@ void AlarmHandler::prepare_alarm_attr()
 				unacknowledgedNormalAlarms_sz++;
 				almstate = "RTNUN";
 			}
-			else if(ai->second.stat == S_NORMAL && ai->second.ack == ACK)
+			else if(ai->second.stat == S_NORMAL && ai->second.ack == ACK && !ai->second.error)
 			{
 				normalAlarms_read[normalAlarms_sz] = ai->second.name;
 				attr_alarmNormal_read[normalAlarms_sz] = const_cast<char*>(normalAlarms_read[normalAlarms_sz].c_str());
diff --git a/src/alarm_table.cpp b/src/alarm_table.cpp
index 47c7763905ae37f7f770d4d72c32ea29aee8ff4f..64f1badd7fd0bf274691e6272b16b63daf4c65a6 100644
--- a/src/alarm_table.cpp
+++ b/src/alarm_table.cpp
@@ -356,9 +356,18 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
 		}
 		bool status_err_delay;
 		if(err_delay > 0)
-			status_err_delay = (!res.ex_reason.empty() || !res.ex_desc.empty() || !res.ex_origin.empty()) && (found->second.err_counter >= 1) && ((now.tv_sec - err_delay) > found->second.ts_err_delay.tv_sec);	//error is present and err delay has passed
+			status_err_delay = (!res.valid) && (found->second.err_counter >= 1) && ((now.tv_sec - err_delay) > found->second.ts_err_delay.tv_sec);	//error is present and err delay has passed
 		else
-			status_err_delay = (!res.ex_reason.empty() || !res.ex_desc.empty() || !res.ex_origin.empty());
+			status_err_delay = (!res.valid);
+		if(!status_err_delay && !res.valid)	//formula result not valid, waiting for err_delay
+		{
+			found->second.attr_values_delay = attr_values;		//save last attr_values to be used in timer_update if this alarm pass over on or off delay
+			found->second.err_counter++;
+			if(found->second.err_counter == 1)
+				found->second.ts_err_delay = gettime();		//first occurrance of this error, now begin to wait for err delay
+			vlock->readerOut();
+			return ret_changed;
+		}
 		found->second.quality = res.quality;
 		found->second.ex_reason = res.ex_reason;
 		found->second.ex_desc = res.ex_desc;
@@ -523,7 +532,7 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
 			found->second.on_counter = 0;
 			found->second.off_counter++;
 		}
-		if(!found->second.ex_reason.empty() || !found->second.ex_desc.empty() || !found->second.ex_origin.empty())
+		if(!res.valid)
 		{
 			found->second.err_counter++;
 		}
@@ -566,7 +575,7 @@ bool alarm_table::timer_update()
 		bool status_on_delay=false;
 		bool status_off_delay=false;
 		bool status_err_delay=false;
-		if(err_delay > 0)		//if enabled off delay
+		if(err_delay > 0)		//if enabled err delay
 			status_err_delay = (i->second.err_counter >= 1) && ((ts.tv_sec - err_delay) > i->second.ts_err_delay.tv_sec);	//waiting for err delay has passed
 
 		if(i->second.on_delay == 0 && i->second.off_delay == 0 && err_delay == 0 && !i->second.shelved && i->second.silenced <=0)
diff --git a/src/alarm_table.h b/src/alarm_table.h
index 3d0bc84dce35b564c53ec325b3ec2fb23433d5f2..321b8e3ac7f47b0a3e6cd2c051985b8626eea68e 100644
--- a/src/alarm_table.h
+++ b/src/alarm_table.h
@@ -112,9 +112,11 @@ struct rwlock_t
 
 struct formula_res_t
 {
-	formula_res_t(){value=0;quality=Tango::ATTR_VALID;ex_reason=string("");ex_desc=string("");ex_origin=string("");}
+	formula_res_t(){value=0;valid=false;quality=Tango::ATTR_VALID;ex_reason=string("");ex_desc=string("");ex_origin=string("");}
 	double value;
 	int quality;
+	bool valid;
+	string error;
 	Tango::DevErrorList 	errors;	//TODO: error stack
 	string ex_reason;
 	string ex_desc;
@@ -145,120 +147,168 @@ struct formula_res_t
 		{
 			formula_res_t res;
 			res.value = value == e.value;
+			res.valid = valid && e.valid;
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator!=(const formula_res_t& e)
 		{
 			formula_res_t res;
 			res.value = value != e.value;
+			res.valid = valid && e.valid;
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator<=(const formula_res_t& e)
 		{
 			formula_res_t res;
 			res.value = value <= e.value;
+			res.valid = valid && e.valid;
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator>=(const formula_res_t& e)
 		{
 			formula_res_t res;
 			res.value = value >= e.value;
+			res.valid = valid && e.valid;
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator<(const formula_res_t& e)
 		{
 			formula_res_t res;
 			res.value = value < e.value;
+			res.valid = valid && e.valid;
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator>(const formula_res_t& e)
 		{
 			formula_res_t res;
 			res.value = value > e.value;
+			res.valid = valid && e.valid;
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator||(const formula_res_t& e)
 		{
 			formula_res_t res;
-			res.value = value || e.value;
+			res.value = (valid && value) || (e.valid && e.value);
+			res.valid = (valid && value) || (e.valid && e.value) || (valid && e.valid);
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator&&(const formula_res_t& e)
 		{
 			formula_res_t res;
-			res.value = value && e.value;
+			res.value = !((valid && !value) || (e.valid && !e.value)) || (valid && value && e.valid && e.value);
+			res.valid = (valid && !value) || (e.valid && !e.value) || (valid && e.valid);
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator+(const formula_res_t& e)
 		{
 			formula_res_t res;
 			res.value = value + e.value;
+			res.valid = valid && e.valid;
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator-(const formula_res_t& e)
 		{
 			formula_res_t res;
 			res.value = value - e.value;
+			res.valid = valid && e.valid;
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator*(const formula_res_t& e)
 		{
 			formula_res_t res;
 			res.value = value * e.value;
+			res.valid = valid && e.valid;
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	formula_res_t operator/(const formula_res_t& e)
 		{
 			formula_res_t res;
 			res.value = value / e.value;
+			res.valid = valid && e.valid;
 			res.quality = combine_quality(quality, e.quality);
-			res.ex_reason = combine_exception(ex_reason, e.ex_reason);
-			res.ex_desc = combine_exception(ex_desc, e.ex_desc);
-			res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			if(!res.valid)
+			{
+				res.ex_reason = combine_exception(ex_reason, e.ex_reason);
+				res.ex_desc = combine_exception(ex_desc, e.ex_desc);
+				res.ex_origin = combine_exception(ex_origin, e.ex_origin);
+			}
 			return res;
 		}
 	/*string operator<<(const formula_res_t& e)