For complex widgets there is bug. During form validation "_traverse" method doesn't change form.custom.widget. But field.widget(field, value) return correct representation. This is lead to wrong field widget output for custom form and custom widget when error occurred. Solution is simple:
--- sqlhtml.py +++ sqlhtml.py @@ -909,8 +909,10 @@ if hasattr(field, 'widget') and field.widget\ and fieldname in request_vars: row_id = '%s_%s%s' % (self.table,fieldname,SQLFORM.ID_ROW_SUFFIX) - self.field_parent[row_id].components = [field.widget(field, value)] + widget = field.widget(field, value) + self.field_parent[row_id].components = [ widget ] self.field_parent[row_id]._traverse(False) + self.custom.widget[ fieldname ] = widget ## also update widget for custom form creation return ret if record_id and record_id != self.record_id: